home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-08 | 200.6 KB | 8,361 lines | [TEXT/CWIE] |
- //
- // GrayCouncil
- // Copyright ©1996 by Trygve Isaacson. All Rights Reserved.
- //
- // Before using any of the GrayCouncil source code, read and
- // follow the licensing info in the accompanying documentation
- // or contact:
- // <trygve@kagi.com>
- // <http://www.kagi.com/authors/trygve/>
- //
- // GrayCouncil provides a set of standard C++ classes that implement
- // the standard Apple Grayscale Appearance. The core classes do not
- // require any other code such as a particular class framework.
- // There are separate files provided that plug the GrayCouncil core
- // into class frameworks.
- //
- // Classes defined below:
- // AGAObject -- abstract base class for most others
- // MExclusiveObject -- mixin class for mutual exclusivity (e.g. radio)
- // AGATextStyle -- text style attributes container
- // AGAStaticText -- simple string object
- // AGAPushButton -- push button with auto default outline capability
- // AGACheckBox -- check box with mixed state capability
- // AGARadioButton -- radio button with mixed state capability
- // MIconButtonObject -- mixin class for icon buttons
- // AGAIconPushButton -- AGAPushButton subclass for icon push buttons
- // AGAIconCheckBox -- AGACheckBox subclass for on/off icon buttons
- // AGAIconRadioButton -- AGARadioButton subclass for mutually exclusive
- // on/off icon buttons
- // AGATrackingIndicator -- abstract superclass for scroll bar and slider
- // AGAScrollBar -- scroll bar with 32-bit values, live tracking, and
- // proportional indicator capabilities
- // AGASlider -- slider with pointy or rectangular indicator, optional
- // labels, live tracking, proportional indicator capabilities
- // AGAPopupMenu -- popup menu with optional title
- // AGALittleArrows -- little up/down arrows with notification
- // AGADisclosureTriangle -- disclosure triangle with animation
- // AGAProgressIndicator -- determinate or indeterminate progress gauge
- // with moving determinate origin capability
- // AGASeparator -- separator line with automatic directionality
- // AGAGroupBox -- primary or secondary group box with optional title or
- // room for external title or control
- //
-
- #include "GrayCouncil.h"
-
- #include <limits.h>
- #include <plstringfuncs.h>
-
- //
- // Global variables ---------------------------------------------------
- //
-
- const Str255 gGrayCouncilCopyright = kGrayCouncilCopyright;
-
- Boolean gAGAHasColorQD;
-
- UInt32 gAGADefaults = 0;
-
- // This is global group maintainer.
- static AGAGroupsContainer* gGroupsContainer;
-
- // Standard system text style, used by most standard controls.
- AGATextStyle gAGAStdSystemStyle = AGATextStyle();
-
- // Standard small text style, used for slider labels.
- AGATextStyle gAGAStdSmallStyle = AGATextStyle(applFont, 10, normal);
-
- // Extra small text style, a de facto standard.
- AGATextStyle gAGAExtraSmallStyle = AGATextStyle(applFont, 9, normal);
-
- // These are the AGA-specified color values.
- RGBColor gAGARamp[kNumRampColors] =
- {
- {65535, 65535, 65535}, // rW white
- {61166, 61166, 61166}, // r1 lightest gray
- {56797, 56797, 56797}, // r2
- {52428, 52428, 52428}, // r3
- {48059, 48059, 48059}, // r4 light grays
- {43690, 43690, 43690}, // r5
- {39321, 39321, 39321}, // r6
- {34952, 34952, 34952}, // r7
- {30583, 30583, 30583}, // r8 dark grays
- {26214, 26214, 26214}, // r9
- {21845, 21845, 21845}, // r10
- {17476, 17476, 17476}, // r11
- {8738, 8738, 8738}, // r12 darkest gray
- {13107, 13107, 13107}, // rA additional gray value
- {0, 0, 0}, // rB black
- {52428, 52428, 65535}, // rA1 lightest purple
- {39321, 39321, 65535}, // rA2 light purple
- {26214, 26214, 65535}, // rA3 dark purple
- {13107, 13107, 26214} // rA4 darkest purple
- };
-
- //
- // Initialization -----------------------------------------------------
- //
- // Must be called by client application after initializing the toolbox,
- // and before any other Gray Council calls are made.
- // The framework-specific initialization functions call this automatically.
- //
-
- OSErr InitGrayCouncil()
- {
- OSErr result;
- SInt32 gestaltResponse;
-
- //
- // Initialize some basic globals.
- //
-
- // Default flags. Only live scrolling is on by default.
- gAGADefaults = kAGALiveScrolling;
-
- // Set global Color QuickDraw flag.
- result = ::Gestalt(gestaltQuickdrawVersion, &gestaltResponse);
- gAGAHasColorQD = (result == noErr) && (gestaltResponse != gestaltOriginalQD);
-
- // Allocate the group container.
- gGroupsContainer = new AGAGroupsContainer;
-
- // Try to allocate the offscreen images.
- result = AGARadioButton::AllocateRadioImages();
- result = AGAProgressIndicator::AllocateProgressImages();
-
- return result;
- }
-
- #pragma segment GrayCouncilCore1
-
- //
- // Static routines used only inside this file -------------------------
- //
-
- static SInt16 MinSInt16(SInt16 a, SInt16 b) { return (a < b) ? a : b; }
- static SInt16 MaxSInt16(SInt16 a, SInt16 b) { return (a > b) ? a : b; }
- static SInt32 MinSInt32(SInt32 a, SInt32 b) { return (a < b) ? a : b; }
- static SInt32 MaxSInt32(SInt32 a, SInt32 b) { return (a > b) ? a : b; }
-
- static void DelayFuture(SInt32 delayTicks)
- {
- // Delay for the specified number of ticks.
-
- SInt32 dontCare;
- ::Delay(delayTicks, &dontCare);
- }
-
- static void DelayFutureWhileStillDown(SInt32 delayTicks)
- {
- // Delay for the specified number of ticks, but bail
- // out if the user lets go of the mouse first.
-
- SInt32 future = delayTicks + ::TickCount();
-
- while (::StillDown() && (::TickCount() < future))
- {};
- }
-
- static SInt32 RuntimeJustify(SInt32 userJust)
- {
- // Return the actual runtime justification value for
- // the supplied value. The caller can use the result
- // alone to know determine drawing direction.
- // If the supplied value specifies default, we need
- // to check the current system script direction.
- // Otherwise, whatever was specified is OK as is.
-
- if (userJust == teFlushDefault)
- {
- if (::GetSysDirection() == 0)
- return teFlushLeft;
- else
- return teFlushRight;
- }
- else
- return userJust;
- }
-
- //
- // AGATextStyle --------------------------------------------------------
- //
-
- AGATextStyle::AGATextStyle()
- {
- // Default constructor, use system font.
-
- mFontNum = systemFont; // typically Chicago
- mFontSize = 0; // application size, typically 12-point
- mFontStyle = normal;
- }
-
- AGATextStyle::AGATextStyle(SInt16 fontNum, SInt16 fontSize, Style fontStyle)
- {
- // Construct with direct parameters.
-
- mFontNum = fontNum;
- mFontSize = fontSize;
- mFontStyle = fontStyle;
- }
-
- AGATextStyle::AGATextStyle(StringPtr fontName, SInt16 fontSize, Style fontStyle)
- {
- // Construct by converting font name to font number.
-
- ::GetFNum(fontName, &mFontNum);
- mFontSize = fontSize;
- mFontStyle = fontStyle;
- }
-
- AGATextStyle::AGATextStyle(const TextStyle& textStyle)
- {
- // Construct by copying another text style.
-
- mFontNum = textStyle.tsFont;
- mFontSize = textStyle.tsSize;
- mFontStyle = textStyle.tsFace;
- }
-
- #ifdef __PowerPlant__
- AGATextStyle::AGATextStyle(ResIDT inTextTraitsID)
- {
- // Construct from a PowerPlant Text Traits resource.
-
- TextTraitsH aTTHandle = UTextTraits::LoadTextTraits(inTextTraitsID);
-
- if (aTTHandle == NULL) // likely, cos there is no "0" Txtr resource
- {
- mFontNum = systemFont; // typically Chicago
- mFontSize = 0; // application size, typically 12-point
- mFontStyle = normal;
- }
- else
- {
- mFontNum = (**aTTHandle).fontNumber;
- mFontSize = (**aTTHandle).size;
- mFontStyle = (**aTTHandle).style;
-
- if (mFontNum == UTextTraits::fontNumber_Unknown) // means use supplied font name
- {
- Str255 fontName;
-
- PLstrcpy(fontName, (**aTTHandle).fontName);
- ::GetFNum(fontName, &mFontNum);
- }
- }
- }
- #endif // __PowerPlant__
-
- void AGATextStyle::PrepareForDrawing() const
- {
- // Set the text pen for subsequent drawing.
-
- ::TextFont(mFontNum);
- ::TextSize(mFontSize);
- ::TextFace(mFontStyle);
- }
-
- //
- // AGAObject ---------------------------------------------------------------
- //
-
- AGAObject::AGAObject(Rect* bounds)
- {
- // Construct enabled.
-
- mBounds = *bounds;
- mEnabled = TRUE;
- mBackgroundEraseColor = gAGARamp[r2];
- }
-
- AGAObject::~AGAObject()
- {
- }
-
- void AGAObject::GetObjectBounds(Rect* bounds)
- {
- // Return current bounds.
-
- *bounds = mBounds;
- }
-
- void AGAObject::SetObjectBounds(Rect* bounds, Boolean redraw)
- {
- // Change bounds, redraw if specified.
-
- mBounds = *bounds;
-
- if (redraw)
- this->DrawObject();
- }
-
- void AGAObject::DrawObject()
- {
- // Override to draw particular type of object.
- }
-
- Boolean AGAObject::ContainsMouse(Point mouseLocation)
- {
- // Return true if mouse will hit object.
-
- return ::PtInRect(mouseLocation, &mBounds);
- }
-
- Boolean AGAObject::TrackMouse(Point mouseLocation)
- {
- // Process mouse tracking, return true if tracking
- // eventually "did something". Return false if
- // tracking had no ultimate effect, e.g. mouse
- // up outside a push button.
-
- Boolean finishedIn = FALSE;
- Boolean wasIn = FALSE;
- Boolean isIn;
- Boolean isButtonDown = TRUE; // ensure at least one time through
- Point newMouseLocation;
-
- while (isButtonDown)
- {
- ::GetMouse(&newMouseLocation); // gives local coordinates
-
- isIn = this->HitTest(newMouseLocation);
-
- if (isIn != wasIn)
- this->SetTrackingState(isIn);
-
- wasIn = isIn;
-
- isButtonDown = ::StillDown();
- }
-
- if (isIn) // if finished IN, restore normal appearance
- this->SetTrackingState(kTrackingOut);
-
- return isIn;
- }
-
- void AGAObject::SetEnable(Boolean isEnabled, Boolean redraw)
- {
- // Set object enable state, redraw if specified.
-
- mEnabled = isEnabled;
-
- if (redraw)
- this->DrawObject();
- }
-
- void AGAObject::SetBackgroundEraseColor(RGBColor* color)
- {
- // Set color to be used when erasing background.
- // Most views don't need this. Default is AGA ramp r2.
- // AGAStaticText and AGADisclosureTriangle need to
- // erase their background, so if your background is
- // not r2 (white, for example), call this to set it.
-
- mBackgroundEraseColor = *color;
- }
-
- Boolean AGAObject::HitTest(Point mouseLocation)
- {
- // Return true if mouse is inside tracking area of
- // object. This function may be overridden for
- // classes that do not have simple rectangular
- // boundary hit testing.
-
- return ::PtInRect(mouseLocation, &mBounds);
- }
-
- void AGAObject::SetTrackingState(Boolean isIn)
- {
- // Override to draw the object in the appropriate
- // state during tracking. If isIn is true, it means
- // that the mouse is now in the positive hit test
- // area of the object.
- }
-
- //
- // AGAStaticText ---------------------------------------------------------------
- //
- // This class draws a static text label.
- //
-
- AGAStaticText::AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification)
- : AGAObject(bounds)
- {
- // Construct with empty string.
-
- mJustification = justification;
- mTitle[0];
- mTextStyle = textStyle;
- }
-
- AGAStaticText::AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification, StringPtr title)
- : AGAObject(bounds)
- {
- // Construct with supplied string.
-
- mJustification = justification;
- PLstrcpy(mTitle, title);
- mTextStyle = textStyle;
- }
-
- AGAStaticText::AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification, SInt16 stringListResourceID, SInt16 stringIndex)
- : AGAObject(bounds)
- {
- // Construct by getting string from specified resource.
-
- mJustification = justification;
- ::GetIndString(mTitle, stringListResourceID, stringIndex);
- mTextStyle = textStyle;
- }
-
- AGAStaticText::~AGAStaticText()
- {
- }
-
- void AGAStaticText::DrawObject()
- {
- CleansePen();
-
- // Paint gray over possible obsolete text, draw current text.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- ::RGBForeColor(&mBackgroundEraseColor);
- else
- ::RGBForeColor(&gAGARamp[rW]);
-
- ::PaintRect(&mBounds);
-
- AGAStringOut(mTitle, &mBounds, truncEnd, mJustification, mEnabled ? kNormalOutput : kDisabledOutput, deep, mTextStyle);
- }
-
- CleansePen();
- }
-
- void AGAStaticText::SetTitle(StringPtr title, Boolean redraw)
- {
- // Change text, redraw if specified.
-
- PLstrcpy(mTitle, title);
-
- if (redraw)
- this->DrawObject();
- }
-
- //
- // AGAPushButton ---------------------------------------------------------------
- //
- // This class implements a standard text pushbutton object.
- //
-
- AGAPushButton::AGAPushButton(Rect* bounds, const AGATextStyle& textStyle)
- : AGAObject(bounds)
- {
- // Construct with initial empty button title.
-
- mIsDefault = FALSE;
- mFrameInside = TRUE;
- mTitle[0];
- mTextStyle = textStyle;
- }
-
- AGAPushButton::AGAPushButton(Rect* bounds, const AGATextStyle& textStyle, StringPtr title)
- : AGAObject(bounds)
- {
- // Construct with specified button title.
-
- mIsDefault = FALSE;
- mFrameInside = TRUE;
- PLstrcpy(mTitle, title);
- mTextStyle = textStyle;
- }
-
- AGAPushButton::AGAPushButton(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex)
- : AGAObject(bounds)
- {
- // Construct by getting button title from specified resource.
-
- mIsDefault = FALSE;
- mFrameInside = TRUE;
- ::GetIndString(mTitle, stringListResourceID, stringIndex);
- mTextStyle = textStyle;
- }
-
- AGAPushButton::~AGAPushButton()
- {
- }
-
- void AGAPushButton::DrawObject()
- {
- // Draw button in normal unpressed state.
-
- this->DrawButton(kNotPressed);
- }
-
- void AGAPushButton::SetTitle(StringPtr title, Boolean redraw)
- {
- // Change button title, redraw if specified.
-
- PLstrcpy(mTitle, title);
-
- if (redraw)
- this->DrawObject();
- }
-
- void AGAPushButton::SetDefault(Boolean isDefault, Boolean frameInside)
- {
- // Set default state. If mIsDefault is true, the button will
- // be drawn with a default button outline. If mFrameInside
- // is true, the outline will be inside mBounds and the button
- // will be drawn inset from there; if mFrameInside is false,
- // the outline will be outside mBounds and the button will
- // be drawn at mBounds.
-
- mIsDefault = isDefault;
- mFrameInside = frameInside;
- }
-
- void AGAPushButton::DrawButton(Boolean pressed)
- {
- CleansePen();
-
- // Draw the button in the appropriate state.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (! mEnabled)
- this->DrawButtonDisabled(deep);
- else if (pressed)
- this->DrawButtonPressed(deep);
- else
- this->DrawButtonNormal(deep);
- }
-
- CleansePen();
- }
-
- Boolean AGAPushButton::HitTest(Point mouseLocation)
- {
- // Return true if the mouse is in the button.
- // Account for case where default button outline
- // is inside mBounds.
-
- Rect r = mBounds;
-
- if (mIsDefault && mFrameInside)
- ::InsetRect(&r, 3, 3);
-
- return ::PtInRect(mouseLocation, &r);
- }
-
- void AGAPushButton::SetTrackingState(Boolean isIn)
- {
- // Draw the button pressed or unpressed as specified.
-
- this->DrawButton(isIn);
- }
-
- void AGAPushButton::DrawButtonNormal(Boolean deep)
- {
- // Draw the button in enabled/unpressed state.
-
- Rect r = mBounds;
-
- if (mIsDefault && mFrameInside)
- ::InsetRect(&r, 3, 3);
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(r.right - r.left - 6, 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, r.bottom - r.top - 6);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(- (r.right - r.left - 6), 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, -(r.bottom - r.top - 6));
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
-
- // Add 1st inner pixels.
- ::MoveTo(r.left + 1, r.top + 2);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::Line(0, 0);
- ::Move(r.right - r.left - 5, 0);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, r.bottom - r.top - 6);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(- (r.right - r.left - 6), 0);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Move(-1, 0);
- ::Line(-1, -1);
-
- // Add 2nd inner pixels.
- ::MoveTo(r.left + 2, r.bottom - 4);
- ::RGBForeColor(&gAGARamp[rW]);
- ::Line(0, -(r.bottom - r.top - 6));
- ::Line(1, 1);
- ::Line(0, -1);
- ::Line(r.right - r.left - 7, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, r.bottom - r.top - 7);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(- (r.right - r.left - 7), 0);
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRoundRect(&r, 7, 7);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRoundRect(&r, 7, 7);
- }
-
- // Draw the title.
- AGAStringOut(mTitle, &r, truncMiddle, teJustCenter, kNormalOutput, deep, mTextStyle);
-
- // Draw the default button outline.
- this->DrawOutlineNormal(deep);
- }
-
- void AGAPushButton::DrawButtonPressed(Boolean deep)
- {
- // Draw the button in enabled/pressed state.
-
- Rect r = mBounds;
-
- if (mIsDefault && mFrameInside)
- ::InsetRect(&r, 3, 3);
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r9]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(r.right - r.left - 6, 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, r.bottom - r.top - 6);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(- (r.right - r.left - 6), 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, -(r.bottom - r.top - 6));
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
-
- // Add 1st inner pixels.
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[r11]);
- ::Line(0, -(r.bottom - r.top - 5));
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(r.right - r.left - 5, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(0, r.bottom - r.top - 6);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(- (r.right - r.left - 5), 0);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, 0);
-
- // Add 2nd inner pixels.
- ::MoveTo(r.left + 2, r.bottom - 4);
- ::RGBForeColor(&gAGARamp[r10]);
- ::Line(0, -(r.bottom - r.top - 7));
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(r.right - r.left - 7, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, r.bottom - r.top - 7);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(- (r.right - r.left - 7), 0);
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintRoundRect(&r, 7, 7);
- }
-
- // Draw the title.
- AGAStringOut(mTitle, &r, truncMiddle, teJustCenter, kInverseOutput, deep, mTextStyle);
-
- // Draw the default button outline.
- this->DrawOutlineNormal(deep);
- }
-
- void AGAPushButton::DrawButtonDisabled(Boolean deep)
- {
- // Draw the button in disabled/unpressed state.
-
- Rect r = mBounds;
-
- if (mIsDefault && mFrameInside)
- ::InsetRect(&r, 3, 3);
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::Line(0, 0);
- ::Move(1, 0);
- ::Line(r.right - r.left - 6, 0);
- ::Line(0, 0);
- ::Move(1, 1);
- ::Line(0, 0);
- ::Move(1, 1);
- ::Line(0, 0);
- ::Move(0, 1);
- ::Line(0, r.bottom - r.top - 6);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::Line(- (r.right - r.left - 6), 0);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::Line(0, 0);
- ::Move(0, -1);
- ::Line(0, -(r.bottom - r.top - 6));
- ::Line(0, 0);
-
- // Add 1st inner pixels.
- ::MoveTo(r.left + 1, r.top + 2);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::Line(0, 0);
- ::Move(r.right - r.left - 5, 0);
- ::Line(0, 0);
- ::Move(1, 1);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, r.bottom - r.top - 6);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(- (r.right - r.left - 6), 0);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Move(-1, 0);
- ::Line(-1, -1);
-
- // Add 2nd inner pixels.
- ::MoveTo(r.left + 2, r.bottom - 4);
- ::RGBForeColor(&gAGARamp[r1]);
- ::Line(0, -(r.bottom - r.top - 6));
- ::Line(1, 1);
- ::Line(0, -1);
- ::Line(r.right - r.left - 7, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Line(0, r.bottom - r.top - 7);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(- (r.right - r.left - 7), 0);
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRoundRect(&r, 7, 7);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRoundRect(&r, 7, 7);
- }
-
- // Draw the title.
- AGAStringOut(mTitle, &r, truncMiddle, teJustCenter, kDisabledOutput, deep, mTextStyle);
-
- // Draw the default button outline.
- this->DrawOutlineDisabled(deep);
-
- if (! deep)
- {
- if (mIsDefault)
- ::InsetRect(&r, -3, -3);
-
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenPat(&qd.gray);
- ::PenMode(patBic);
- ::PaintRect(&r);
-
- ::PenNormal();
- }
- }
-
- void AGAPushButton::DrawOutlineNormal(Boolean deep)
- {
- // Draw the default button outline in normal
- // state if the button has one. It may be either
- // inside or outside mBounds.
-
- // If we are drawing the outline outside the normal
- // bounds, we should force the clipping to include
- // that outside area, because the framework or whoever
- // may have reduced clipping to our bounds.
-
- if (! mIsDefault)
- return;
-
- Rect r = mBounds;
-
- if (! mFrameInside)
- ::InsetRect(&r, -3, -3);
-
- if (deep)
- {
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 2);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(1, -1);
- ::Move(1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(r.right - r.left - 8, 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(1, 1);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, r.bottom - r.top - 8);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(-1, 1);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(- (r.right - r.left - 8), 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(-1, -1);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, -(r.bottom - r.top - 8));
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
-
- // Draw the interior.
- ::MoveTo(r.left + 1, r.bottom - 4);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(0, -(r.bottom - r.top - 7));
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(r.right - r.left - 8, 0);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[r3]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, r.bottom - r.top - 8);
- ::Line(-2, 2);
- ::Line(-(r.right - r.left - 8), 0);
- ::Move(-1, 0);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[r3]);
- ::Line(0, 0);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, -(r.bottom - r.top - 8));
- ::Line(2, -2);
- ::Line(r.right - r.left - 8, 0);
- ::Line(0, 1);
- ::Line(1, 0);
- ::Line(0, r.bottom - r.top - 8);
- ::Line(-2, 2);
- ::Line(-(r.right - r.left - 8), 0);
- ::Line(0, -1);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(1, 1);
- ::MoveTo(r.left + 3, r.top + 4);
- ::Line(1, -1);
- ::MoveTo(r.right -5, r.top + 3);
- ::Line(1, 1);
- ::MoveTo(r.right -5, r.bottom - 4);
- ::Line(1, -1);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(-1, 1);
- }
- else
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenSize(2, 2);
- ::FrameRoundRect(&r, 11, 11);
- ::PenSize(1, 1);
- }
- }
-
- void AGAPushButton::DrawOutlineDisabled(Boolean deep)
- {
- // Draw the default button outline in disabled
- // state if the button has one. It may be either
- // inside or outside mBounds.
-
- if (! mIsDefault)
- return;
-
- Rect r = mBounds;
-
- if (! mFrameInside)
- ::InsetRect(&r, -3, -3);
-
- if (deep)
- {
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 2);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(1, -1);
- ::Move(1, -1);
- ::Line(0, 0);
- ::Move(1, 0);
- ::Line(r.right - r.left - 8, 0);
- ::Line(0, 0);
- ::Move(1, 1);
- ::Line(1, 1);
- ::Move(1, 1);
- ::Line(0, 0);
- ::Move(0, 1);
- ::Line(0, r.bottom - r.top - 8);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::Line(-1, 1);
- ::Move(-1, 1);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::Line(- (r.right - r.left - 8), 0);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::Line(-1, -1);
- ::Move(-1, -1);
- ::Line(0, 0);
- ::Move(0, -1);
- ::Line(0, -(r.bottom - r.top - 8));
- ::Line(0, 0);
-
- // Draw the interior.
- ::MoveTo(r.left + 1, r.bottom - 4);
- ::RGBForeColor(&gAGARamp[r1]);
- ::Line(0, -(r.bottom - r.top - 7));
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(r.right - r.left - 8, 0);
- ::Move(3, 2);
- ::RGBForeColor(&gAGARamp[r6]);
- ::Line(0, r.bottom - r.top - 7);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(-(r.right - r.left - 7), 0);
- ::Move(-2, -2);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Line(1, 1);
- ::Line(0, -(r.bottom - r.top - 7));
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(1, 0);
- ::Line(0, -1);
- ::Line(r.right - r.left - 7, 0);
- ::Line(-1, -1);
- ::Move(-1, 2);
- ::Line(2, 0);
- ::Move(-1, 1);
- ::Line(1, 0);
- ::Line(0, r.bottom - r.top - 9);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(-1, 0);
- ::Line(0, 1);
- ::Line(-(r.right - r.left - 8), 0);
- ::Line(0, -2);
- ::Line(1, 1);
- }
- else
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenSize(2, 2);
- ::FrameRoundRect(&r, 11, 11);
- ::PenSize(1, 1);
- }
- }
-
- //
- // AGACheckBox ---------------------------------------------------------------
- //
- // This class implements a standard checkbox object with the additional
- // capability of supporting mixed state.
- //
-
- AGACheckBox::AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, Boolean automaticState)
- : AGAObject(bounds)
- {
- // Construct with initial empty button title.
-
- mValue = kCheckBoxOff;
- mAutomaticState = automaticState;
- mTitle[0];
- mTextStyle = textStyle;
- }
-
- AGACheckBox::AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, StringPtr title, Boolean automaticState)
- : AGAObject(bounds)
- {
- // Construct with specified button title.
-
- mValue = kCheckBoxOff;
- mAutomaticState = automaticState;
- PLstrcpy(mTitle, title);
- mTextStyle = textStyle;
- }
-
- AGACheckBox::AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex, Boolean automaticState)
- : AGAObject(bounds)
- {
- // Construct by getting button title from specified resource.
-
- mValue = kCheckBoxOff;
- mAutomaticState = automaticState;
- ::GetIndString(mTitle, stringListResourceID, stringIndex);
- mTextStyle = textStyle;
- }
-
- AGACheckBox::~AGACheckBox()
- {
- }
-
- void AGACheckBox::DrawObject()
- {
- // Draw button in normal unpressed state.
-
- this->DrawButton(kNotPressed);
- }
-
- Boolean AGACheckBox::TrackMouse(Point mouseLocation)
- {
- // If inherited tracking succeeded and we are set to
- // automatically change our state, toggle it.
-
- Boolean wasItHit = AGAObject::TrackMouse(mouseLocation);
-
- if (wasItHit && mAutomaticState)
- this->SetValue((mValue == kCheckBoxOn) ? kCheckBoxOff : kCheckBoxOn, kRedraw);
-
- return wasItHit;
- }
-
- void AGACheckBox::SetTitle(StringPtr title, Boolean redraw)
- {
- // Change button title, redraw if specified.
-
- PLstrcpy(mTitle, title);
-
- if (redraw)
- this->DrawObject();
- }
-
- SInt32 AGACheckBox::GetValue()
- {
- // Return current state.
-
- return mValue;
- }
-
- void AGACheckBox::SetValue(SInt32 newValue, Boolean redraw)
- {
- // Set current state, redraw if specified and necessary.
-
- if (newValue != mValue)
- {
- mValue = newValue;
-
- if (redraw)
- {
- this->DrawButton(kNotPressed);
- }
- }
- }
-
- void AGACheckBox::DrawButton(Boolean pressed)
- {
- CleansePen();
-
- // Draw the button in the appropriate state.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (! mEnabled)
- this->DrawButtonDisabled(deep);
- else if (pressed)
- this->DrawButtonPressed(deep);
- else
- this->DrawButtonNormal(deep);
- }
-
- CleansePen();
- }
-
- void AGACheckBox::SetTrackingState(Boolean isIn)
- {
- // Draw the button pressed or unpressed as specified.
-
- this->DrawButton(isIn);
- }
-
- void AGACheckBox::DrawButtonNormal(Boolean deep)
- {
- // Draw the button in enabled/unpressed state.
-
- Rect r = mBounds;
-
- r.bottom = r.top + kCheckBoxSize;
- r.right = r.left + kCheckBoxSize;
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
-
- // Draw the edges.
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[rW]);
- ::Line(0, -8);
- ::Line(8, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(0, 8);
- ::Line(-8, 0);
-
- if (mValue == kCheckBoxOn)
- {
- // Draw the X and its shadow.
- ::MoveTo(r.left + 3, r.top + 2);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(5, 5);
- ::Move(0, 1);
- ::Line(-5, -5);
- ::Move(0, 4);
- ::Line(5, -5);
- ::Move(0, 1);
- ::Line(-5, 5);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(1, -1);
- ::Move(2, -2);
- ::Line(2, -2);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(-1, 1);
- ::Move(-2, 2);
- ::Line(-2, 2);
- ::Move(5, 0);
- ::Line(0, 0);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, 0);
- }
- else if (mValue == kCheckBoxMixed)
- {
- // Draw the dash and its shadow.
- ::MoveTo(r.left + 3, r.top + 5);
- ::PenSize(2, 2);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(4, 0);
-
- ::MoveTo(r.left + 4, r.top + 7);
- ::PenSize(1, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(5, 0);
- ::Line(-2, 0);
- }
- }
- else
- {
- // Paint white over previous junk, if any.
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- // Paint frame.
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
-
- // Draw check or dash.
- if (mValue == kCheckBoxOn)
- {
- ::PenSize(1, 1);
- ::MoveTo(r.left, r.top);
- ::Line(kCheckBoxSize-1, kCheckBoxSize-1);
- ::Move(-(kCheckBoxSize-1), 0);
- ::Line(kCheckBoxSize-1, -(kCheckBoxSize-1));
- }
- else if (mValue == kCheckBoxMixed)
- {
- ::PenSize(1, 2);
- ::MoveTo(r.left + 3, r.top + 5);
- ::Line(5, 0);
- }
-
- ::PenNormal();
- }
-
- // Draw the title.
- r = mBounds;
- r.left += (kCheckBoxSize + 6);
- r.bottom = r.top + kCheckBoxSize;
- AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
- }
-
- void AGACheckBox::DrawButtonPressed(Boolean deep)
- {
- // Draw the button in enabled/pressed state.
-
- Rect r = mBounds;
-
- r.bottom = r.top + kCheckBoxSize;
- r.right = r.left + kCheckBoxSize;
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
-
- // Draw the edges.
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[r10]);
- ::Line(0, -8);
- ::Line(8, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r6]);
- ::Line(0, 8);
- ::Line(-8, 0);
-
- if (mValue == kCheckBoxOn)
- {
- // Draw the X and its shadow.
- ::MoveTo(r.left + 3, r.top + 2);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(5, 5);
- ::Move(0, 1);
- ::Line(-5, -5);
- ::Move(0, 4);
- ::Line(5, -5);
- ::Move(0, 1);
- ::Line(-5, 5);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[r11]);
- ::Line(1, -1);
- ::Move(2, -2);
- ::Line(2, -2);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[r10]);
- ::Line(-1, 1);
- ::Move(-2, 2);
- ::Line(-2, 2);
- ::Move(5, 0);
- ::Line(0, 0);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[r11]);
- ::Line(0, 0);
- }
- else if (mValue == kCheckBoxMixed)
- {
- // Draw the dash and its shadow.
- ::MoveTo(r.left + 3, r.top + 5);
- ::PenSize(2, 2);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(4, 0);
-
- ::MoveTo(r.left + 4, r.top + 7);
- ::PenSize(1, 1);
- ::RGBForeColor(&gAGARamp[r10]);
- ::Line(5, 0);
- ::Line(-2, 0);
- }
- }
- else
- {
- // Paint white over previous junk, if any.
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- // Paint frame.
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenSize(2, 2);
- ::FrameRect(&r);
-
- // Draw check or dash.
- if (mValue == kCheckBoxOn)
- {
- ::PenSize(1, 1);
- ::MoveTo(r.left, r.top);
- ::Line(kCheckBoxSize-1, kCheckBoxSize-1);
- ::Move(-(kCheckBoxSize-1), 0);
- ::Line(kCheckBoxSize-1, -(kCheckBoxSize-1));
- }
- else if (mValue == kCheckBoxMixed)
- {
- ::PenSize(1, 2);
- ::MoveTo(r.left + 3, r.top + 5);
- ::Line(5, 0);
- }
-
- ::PenNormal();
- }
-
- // Draw the title.
- r = mBounds;
- r.left += (kCheckBoxSize + 6);
- r.bottom = r.top + kCheckBoxSize;
- AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
- }
-
- void AGACheckBox::DrawButtonDisabled(Boolean deep)
- {
- // Draw the button in disabled/unpressed state.
-
- Rect r = mBounds;
-
- r.bottom = r.top + kCheckBoxSize;
- r.right = r.left + kCheckBoxSize;
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::RGBForeColor(&gAGARamp[r7]);
- ::FrameRect(&r);
-
- // Draw the edges.
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[rW]);
- ::Line(0, -8);
- ::Line(8, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, 8);
- ::Line(-8, 0);
-
- if (mValue == kCheckBoxOn)
- {
- // Draw the X and its shadow.
- ::MoveTo(r.left + 3, r.top + 2);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(5, 5);
- ::Move(0, 1);
- ::Line(-5, -5);
- ::Move(0, 4);
- ::Line(5, -5);
- ::Move(0, 1);
- ::Line(-5, 5);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(1, -1);
- ::Move(2, -2);
- ::Line(2, -2);
- ::Move(0, 1);
- ::Line(-1, 1);
- ::Move(-2, 2);
- ::Line(-2, 2);
- ::Move(5, 0);
- ::Line(0, 0);
- ::Move(0, -1);
- ::Line(0, 0);
- }
- else if (mValue == kCheckBoxMixed)
- {
- // Draw the dash and its shadow.
- ::MoveTo(r.left + 3, r.top + 5);
- ::PenSize(2, 2);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(4, 0);
-
- ::MoveTo(r.left + 4, r.top + 7);
- ::PenSize(1, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(5, 0);
- ::Line(-2, 0);
- }
- }
- else
- {
- // Paint white over previous junk, if any.
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
-
- // Paint frame.
- ::PenPat(&qd.gray);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
-
- // Draw check or dash.
- if (mValue == kCheckBoxOn)
- {
- ::PenPat(&qd.black); // 1-pixel diagonals can disappear when qd.gray
- ::MoveTo(r.left + 2, r.top + 2);
- ::Line(kCheckBoxSize-5, kCheckBoxSize-5);
- ::Move(-(kCheckBoxSize-5), 0);
- ::Line(kCheckBoxSize-5, -(kCheckBoxSize-5));
- }
- else if (mValue == kCheckBoxMixed)
- {
- ::PenSize(1, 2);
- ::MoveTo(r.left + 3, r.top + 5);
- ::Line(5, 0);
- }
-
- ::PenNormal();
- }
-
- // Draw the title.
- r = mBounds;
- r.left += (kCheckBoxSize + 6);
- r.bottom = r.top + kCheckBoxSize;
- AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kDisabledOutput, deep, mTextStyle);
- }
-
- //
- // AGAGroupsContainer --------------------------------------------------------
- //
- // This class is used internally to maintain the MExclusiveObject
- // behavior that allows radio buttons to automatically maintain
- // standard radio button group XOR behavior.
- //
-
- void AGAGroupsContainer::AGAAddGroupMember(MExclusiveObject* groupMember)
- {
- // If the supplied object has an ID pair, add it to its
- // group. Create the group if this is the first member.
-
- if ((groupMember->mGroupIDPart1 != kNoGroupID) && (groupMember->mGroupIDPart2 != kNoGroupID))
- {
- AGAGroup* existingGroup = this->FindGroup(groupMember);
-
- if (existingGroup == NULL)
- {
- AGAGroup newGroup;
-
- newGroup.mGroupIDPart1 = groupMember->mGroupIDPart1;
- newGroup.mGroupIDPart2 = groupMember->mGroupIDPart2;
- newGroup.mGroupMembers.push_back(groupMember);
-
- mGroups.push_back(newGroup);
- }
- else
- {
- existingGroup->mGroupMembers.push_back(groupMember);
- }
- }
- }
-
- void AGAGroupsContainer::AGARemoveGroupMember(MExclusiveObject* groupMember)
- {
- // If the supplied object has an ID pair, remove it from its
- // group. Destroy the group if no more members are left in it.
-
- if ((groupMember->mGroupIDPart1 != kNoGroupID) && (groupMember->mGroupIDPart2 != kNoGroupID))
- {
- AGAGroup* existingGroup = this->FindGroup(groupMember);
-
- if (existingGroup != NULL)
- {
- MExclusiveObject** memberPtr = this->FindMemberPtr(existingGroup, groupMember);
-
- if (memberPtr != NULL)
- existingGroup->mGroupMembers.erase(memberPtr);
- }
- }
- }
-
- void AGAGroupsContainer::AGAHitGroupMember(MExclusiveObject* groupMember)
- {
- // If the supplied object has an ID pair, send every other
- // member of its group the TurnOff message.
-
- if ((groupMember->mGroupIDPart1 != kNoGroupID) && (groupMember->mGroupIDPart2 != kNoGroupID))
- {
- AGAGroup* existingGroup = this->FindGroup(groupMember);
-
- if (existingGroup != NULL)
- {
- for (vector<MExclusiveObject*>::iterator p = existingGroup->mGroupMembers.begin();
- p != existingGroup->mGroupMembers.end();
- p++)
- {
- if (*p != groupMember)
- (*p)->TurnOff();
- }
- }
- }
- }
-
- AGAGroup* AGAGroupsContainer::FindGroup(MExclusiveObject* groupMember)
- {
- // Return a pointer to the group that matches the supplied
- // object's ID pair. Return NULL if no such group exists.
-
- for (vector<AGAGroup>::iterator p = mGroups.begin();
- p != mGroups.end();
- p++)
- {
- if ((p->mGroupIDPart1 == groupMember->mGroupIDPart1) &&
- (p->mGroupIDPart2 == groupMember->mGroupIDPart2))
- return p;
- }
-
- return NULL;
- }
-
- MExclusiveObject** AGAGroupsContainer::FindMemberPtr(AGAGroup* itsGroup, MExclusiveObject* groupMember)
- {
- // Return a pointer to the vector item for the specified member.
- // This allows the vector item to operated on (e.g., deleted).
-
- for (vector<MExclusiveObject*>::iterator p = itsGroup->mGroupMembers.begin();
- p != itsGroup->mGroupMembers.end();
- p++)
- {
- if (*p == groupMember)
- return p;
- }
-
- return NULL;
- }
-
- //
- // MExclusiveObject ---------------------------------------------------------------
- //
- // This class is a mixin class for objects that can be included in a
- // group of mutually exclusively selected objects, i.e. radio buttons
- // or icon buttons. When any group member is selected, the others in
- // the group are sent the TurnOff message.
- //
-
- MExclusiveObject::MExclusiveObject(UInt32 groupIDPart1, UInt32 groupIDPart2)
- {
- // Construct by setting the ID pair and adding to
- // the group.
-
- mGroupIDPart1 = groupIDPart1;
- mGroupIDPart2 = groupIDPart2;
-
- gGroupsContainer->AGAAddGroupMember(this);
- }
-
- MExclusiveObject::~MExclusiveObject()
- {
- // Destruct by removing from the group.
-
- gGroupsContainer->AGARemoveGroupMember(this);
- }
-
- void MExclusiveObject::TurnOff()
- {
- // Override as needed.
- }
-
- //
- // AGAOffscreenImage ------------------------------------------------------------
- //
- // AGAOffscreenImage holds the data needed to blast a clipped region
- // of pixel values onto the current port. This is used by the AGARadioButton
- // class to avoid the ultra-tedious pixel-by-pixel drawing of the grayscale
- // radio button images.
- //
-
- AGAOffscreenImage::AGAOffscreenImage()
- {
- mImagePixMap = NULL;
- mClippingRegion = NULL;
- }
-
- AGAOffscreenImage::~AGAOffscreenImage()
- {
- if (mImagePixMap != NULL)
- ::DisposePixMap(mImagePixMap);
-
- if (mClippingRegion != NULL)
- ::DisposeRgn(mClippingRegion);
- }
-
- OSErr AGAOffscreenImage::CreateImageData(Point imageSize,
- SInt8* imageColorIndexes,
- RgnHandle clippingRegion)
- {
- // Allocate an offscreen PixMap to contain the RGB values
- // specified.
-
- const UInt32 kImageDepth = 4;
-
- ::SetRect(&mImageSourceRect, 0, 0, imageSize.h, imageSize.v);
-
- if (clippingRegion != NULL)
- {
- // Copy the supplied clipping region.
-
- mClippingRegion = ::NewRgn();
- if (mClippingRegion == NULL)
- return memFullErr;
-
- ::CopyRgn(clippingRegion, mClippingRegion);
- OSErr result = ::MemError();
- if (result != noErr)
- return result;
- }
-
- //
- // Allocate and set up the PixMap structure.
- //
-
- Ptr imagePtr = ::NewPtr(kImageDepth * imageSize.h * imageSize.v);
-
- if (imagePtr == NULL)
- return memFullErr;
-
- mImagePixMap = ::NewPixMap();
- ::HLockHi((Handle) mImagePixMap);
-
- PixMapPtr pixMapPtr = *mImagePixMap;
-
- pixMapPtr->baseAddr = imagePtr;
- pixMapPtr->rowBytes = (kImageDepth * imageSize.h) | 0x8000;
- pixMapPtr->bounds = mImageSourceRect;
- pixMapPtr->pixelType = RGBDirect;
- pixMapPtr->pixelSize = 32; // direct 32-bit color values
- pixMapPtr->cmpCount = 3; // 3 color components (RGB)
- pixMapPtr->cmpSize = 8; // 8 bits per component
- pixMapPtr->planeBytes = 0;
-
- if (pixMapPtr->pmTable != NULL)
- {
- // We're using direct color, so toss the table.
- ::DisposeCTable(pixMapPtr->pmTable);
- pixMapPtr->pmTable = NULL;
- }
-
- pixMapPtr->pmReserved = 0;
-
- //
- // Finally, set the pixel RGB color values.
- //
-
- UInt32* pixelPtr = (UInt32*) imagePtr;
- UInt32 numPixels = imageSize.h * imageSize.v;
- SInt8* indexPtr = imageColorIndexes;
-
- for (UInt32 pixelIndex = 0; pixelIndex < numPixels; pixelIndex++)
- {
- SInt8 rampIndex = *indexPtr++;
-
- if (rampIndex == OUT)
- *pixelPtr++ = 0x0000;
- else
- {
- RGBColor rampColor = gAGARamp[rampIndex];
-
- //
- // Construct 32-bit color value.
- // Assuming red is RRrr, blue is BBbb, green is GGgg,
- // we want 0x00RRGGBB, using high byte of each color.
- // This way we toss the low-order (LSB) color data.
- //
-
- UInt32 pixelValue =
- ((((UInt32) rampColor.red) & 0x0000FF00) << 8) |
- (((UInt32) rampColor.green) & 0x0000FF00) |
- ((((UInt32) rampColor.blue) & 0x0000FF00) >> 8);
-
- *pixelPtr++ = pixelValue;
- }
- }
-
- return noErr;
- }
-
- void AGAOffscreenImage::DrawImage(SInt16 imageHOrigin, SInt16 imageVOrigin)
- {
- // Blast the offscreen image data into the current
- // port at the specified coordinate location.
-
- RGBColor savedBackColor;
- GrafPtr currentPort;
- Rect outputRect = mImageSourceRect;
-
- ::GetBackColor(&savedBackColor);
- ::RGBBackColor(&gAGARamp[rW]); // need white BG for desired CopyBits behavior
-
- ::OffsetRect(&outputRect, imageHOrigin, imageVOrigin);
-
- if (mClippingRegion != NULL)
- ::OffsetRgn(mClippingRegion, imageHOrigin, imageVOrigin);
-
- ::GetPort(¤tPort);
- ::CopyBits((BitMapPtr) *mImagePixMap,
- &(currentPort->portBits),
- &mImageSourceRect,
- &outputRect,
- srcCopy,
- mClippingRegion);
-
- if (mClippingRegion != NULL)
- ::OffsetRgn(mClippingRegion, - imageHOrigin, - imageVOrigin);
-
- ::RGBBackColor(&savedBackColor);
- }
-
- void AGAOffscreenImage::DrawPattern(Rect* imageRect)
- {
- // Blast the offscreen image data into the current
- // port, starting at the specified coordinate location,
- // repeating tiled until the imageRect is filled.
-
- RGBColor savedBackColor;
- GrafPtr currentPort;
- Rect outputRect;
-
- ::GetBackColor(&savedBackColor);
- ::RGBBackColor(&gAGARamp[rW]); // need white BG for desired CopyBits behavior
-
- if (mClippingRegion != NULL)
- ::OffsetRgn(mClippingRegion, imageRect->left, imageRect->top);
-
- ::GetPort(¤tPort);
-
- outputRect.top = imageRect->top;
- outputRect.bottom = outputRect.top + mImageSourceRect.bottom;
-
- while (outputRect.top < imageRect->bottom)
- {
- outputRect.left = imageRect->left;
- outputRect.right = outputRect.left + mImageSourceRect.right;
-
- while (outputRect.left < imageRect->right)
- {
- ::CopyBits((BitMapPtr) *mImagePixMap,
- &(currentPort->portBits),
- &mImageSourceRect,
- &outputRect,
- srcCopy,
- mClippingRegion);
-
- ::OffsetRect(&outputRect, mImageSourceRect.right, 0);
- }
-
- ::OffsetRect(&outputRect, 0, mImageSourceRect.bottom);
- }
-
- if (mClippingRegion != NULL)
- ::OffsetRgn(mClippingRegion, - imageRect->left, - imageRect->top);
-
- ::RGBBackColor(&savedBackColor);
- }
-
- //
- // AGARadioButton ---------------------------------------------------------------
- //
- // This class implements a standard radio button object,
- // with the additional capabilities of automatic handling of
- // radio group mutual exclusivity, and mixed state.
- //
-
- // Each radio button drawing state has an offscreen image.
- AGAOffscreenImage* AGARadioButton::mgOffscreenRadioImages[kNumRadioImages];
-
- // These are the color ramp indexes that are used to build the offscreen images.
- SInt8 AGARadioButton::kRadioImageValues[kNumRadioImages][kRadioImageHeight][kRadioImageWidth] =
- {
- { // kRadioNormalOff
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- { OUT, OUT, rB, r10, r2, r2, r2, r4, r11, rB, OUT, OUT },
- { OUT, rB, r4, r2, r1, rW, rW, rW, r2, r7, rB, OUT },
- { r5, r10, r2, r1, rW, rW, r1, r1, r2, r4, r11, r5 },
- { r11, r2, r1, rW, rW, r1, r1, r2, r2, r4, r7, r11 },
- { rB, r2, rW, rW, r1, r1, r2, r2, r4, r4, r7, rB },
- { rB, r2, rW, r1, r1, r2, r2, r4, r4, r5, r7, rB },
- { r11, r4, rW, r1, r2, r2, r4, r4, r5, r5, r7, r11 },
- { r5, r10, r2, r2, r2, r4, r4, r5, r5, r7, r11, r5 },
- { OUT, rB, r7, r4, r4, r4, r5, r5, r7, r7, rB, OUT },
- { OUT, OUT, rB, r10, r7, r7, r7, r7, r11, rB, OUT, OUT },
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- },
-
- { // kRadioNormalOn
- { OUT, OUT, OUT, r5, r12, rB, rB, r12, r5, OUT, OUT, OUT },
- { OUT, OUT, r12, rB, r11, r10, r10, r10, r11, rB, OUT, OUT },
- { OUT, r12, r11, r10, r8, r8, r8, r7, r7, r6, rB, OUT },
- { r5, rB, r10, r8, rB, rB, rB, rB, r6, r6, r11, r5 },
- { r12, r11, r8, rB, rB, rB, rB, rB, rB, r6, r4, r11 },
- { rB, r10, r8, rB, rB, rB, rB, rB, rB, r4, r4, rB },
- { rB, r10, r8, rB, rB, rB, rB, rB, rB, r4, r2, rB },
- { r12, r10, r7, rB, rB, rB, rB, rB, rB, r2, rW, r11 },
- { r5, r12, r7, r6, rB, rB, rB, rB, r2, rW, r11, r5 },
- { OUT, r12, r6, r6, r6, r4, r4, r2, rW, rW, rB, OUT },
- { OUT, OUT, r12, r11, r4, r4, r2, rW, r11, rB, OUT, OUT },
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- },
-
- { // kRadioNormalMixed
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- { OUT, OUT, rB, r10, r2, r2, r2, r4, r11, rB, OUT, OUT },
- { OUT, rB, r4, r2, r1, rW, rW, rW, r2, r7, rB, OUT },
- { r5, r10, r2, r1, rW, rW, r1, r1, r2, r4, r11, r5 },
- { r11, r2, r1, rW, rW, r1, r1, r2, r2, r4, r7, r11 },
- { rB, r2, rW, rB, rB, rB, rB, rB, rB, r4, r7, rB },
- { rB, r2, rW, rB, rB, rB, rB, rB, rB, r5, r7, rB },
- { r11, r4, rW, r1, r2, r2, r4, r4, r5, r5, r7, r11 },
- { r5, r10, r2, r2, r2, r4, r4, r5, r5, r7, r11, r5 },
- { OUT, rB, r7, r4, r4, r4, r5, r5, r7, r7, rB, OUT },
- { OUT, OUT, rB, r10, r7, r7, r7, r7, r11, rB, OUT, OUT },
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- },
-
- { // kRadioPressedOff
- { OUT, OUT, OUT, r5, r12, rB, rB, r12, r5, OUT, OUT, OUT },
- { OUT, OUT, r12, rB, r11, r11, r11, r11, r11, rB, OUT, OUT },
- { OUT, r12, r11, r11, r10, r10, r9, r9, r9, r8, rB, OUT },
- { r5, rB, r11, r10, r10, r9, r9, r8, r8, r8, r11, r5 },
- { r12, r11, r10, r10, r9, r9, r8, r8, r8, r7, r6, r11 },
- { rB, r11, r10, r9, r9, r8, r8, r8, r7, r7, r6, rB },
- { rB, r11, r9, r9, r8, r8, r8, r7, r7, r6, r6, rB },
- { r12, r11, r9, r8, r8, r8, r7, r7, r6, r6, r4, r11 },
- { r5, r12, r9, r8, r8, r7, r7, r6, r6, r4, r10, r5 },
- { OUT, r11, r8, r8, r7, r7, r6, r6, r4, r4, rB, OUT },
- { OUT, OUT, r12, r11, r6, r6, r6, r4, r10, rB, OUT, OUT },
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- },
-
- { // kRadioPressedOn
- { OUT, OUT, OUT, r5, r12, rB, rB, r12, r5, OUT, OUT, OUT },
- { OUT, OUT, r12, rB, r11, r11, r11, r11, r11, rB, OUT, OUT },
- { OUT, r12, r11, r11, r10, r10, r9, r9, r9, r8, rB, OUT },
- { r5, rB, r11, r10, rB, rB, rB, rB, r8, r8, r11, r5 },
- { r12, r11, r10, rB, rB, rB, rB, rB, rB, r7, r6, r11 },
- { rB, r11, r10, rB, rB, rB, rB, rB, rB, r7, r6, rB },
- { rB, r11, r9, rB, rB, rB, rB, rB, rB, r6, r6, rB },
- { r12, r11, r9, rB, rB, rB, rB, rB, rB, r6, r4, r11 },
- { r5, r12, r9, r8, rB, rB, rB, rB, r6, r4, r10, r5 },
- { OUT, r11, r8, r8, r7, r7, r6, r6, r4, r4, rB, OUT },
- { OUT, OUT, r12, r11, r6, r6, r6, r4, r10, rB, OUT, OUT },
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- },
-
- { // kRadioPressedMixed
- { OUT, OUT, OUT, r5, r12, rB, rB, r12, r5, OUT, OUT, OUT },
- { OUT, OUT, r12, rB, r11, r11, r11, r11, r11, rB, OUT, OUT },
- { OUT, r12, r11, r11, r10, r10, r9, r9, r9, r8, rB, OUT },
- { r5, rB, r11, r10, r10, r9, r9, r8, r8, r8, r11, r5 },
- { r12, r11, r10, r10, r9, r9, r8, r8, r8, r7, r6, r11 },
- { rB, r11, r10, rB, rB, rB, rB, rB, rB, r7, r6, rB },
- { rB, r11, r9, rB, rB, rB, rB, rB, rB, r6, r6, rB },
- { r12, r11, r9, r8, r8, r8, r7, r7, r6, r6, r4, r11 },
- { r5, r12, r9, r8, r8, r7, r7, r6, r6, r4, r10, r5 },
- { OUT, r11, r8, r8, r7, r7, r6, r6, r4, r4, rB, OUT },
- { OUT, OUT, r12, r11, r6, r6, r6, r4, r10, rB, OUT, OUT },
- { OUT, OUT, OUT, r5, r11, rB, rB, r11, r5, OUT, OUT, OUT },
- },
-
- { // kRadioDisabledOff
- { OUT, OUT, OUT, r4, r7, r7, r7, r7, r4, OUT, OUT, OUT },
- { OUT, OUT, r7, r7, r1, r1, r1, r3, r7, r7, OUT, OUT },
- { OUT, r7, r3, r1, rW, rW, rW, rW, r1, r5, r7, OUT },
- { r4, r7, r1, rW, rW, rW, rW, rW, r1, r3, r7, r4 },
- { r7, r1, rW, rW, rW, rW, rW, r1, r1, r3, r5, r7 },
- { r7, r1, rW, rW, rW, rW, r1, r1, r3, r3, r5, r7 },
- { r7, r1, rW, rW, rW, r1, r1, r3, r3, r4, r5, r7 },
- { r7, r3, rW, rW, r1, r1, r3, r3, r4, r4, r5, r7 },
- { r4, r7, r1, r1, r1, r3, r3, r4, r4, r5, r7, r4 },
- { OUT, r7, r5, r3, r3, r3, r4, r4, r5, r5, r7, OUT },
- { OUT, OUT, r7, r7, r5, r5, r5, r5, r7, r7, OUT, OUT },
- { OUT, OUT, OUT, r4, r7, r7, r7, r7, r4, OUT, OUT, OUT },
- },
-
- { // kRadioDisabledOn
- { OUT, OUT, OUT, r2, r7, r7, r7, r7, r2, OUT, OUT, OUT },
- { OUT, OUT, r7, r7, r5, r5, r5, r5, r5, r7, OUT, OUT },
- { OUT, r7, r5, r5, r4, r4, r4, r3, r3, r3, r7, OUT },
- { r2, r7, r5, r4, r8, r8, r8, r8, r3, r3, r5, r2 },
- { r7, r5, r4, r8, r8, r8, r8, r8, r8, r3, r1, r5 },
- { r7, r5, r4, r8, r8, r8, r8, r8, r8, r1, r1, r7 },
- { r7, r5, r4, r8, r8, r8, r8, r8, r8, r1, rW, r7 },
- { r7, r5, r3, r8, r8, r8, r8, r8, r8, rW, rW, r5 },
- { r2, r5, r3, r3, r8, r8, r8, r8, rW, rW, r5, r2 },
- { OUT, r7, r3, r3, r3, r1, r1, rW, rW, rW, r7, OUT },
- { OUT, OUT, r7, r7, r1, r1, rW, rW, r5, r7, OUT, OUT },
- { OUT, OUT, OUT, r2, r5, r7, r7, r5, r2, OUT, OUT, OUT },
- },
-
- { // kRadioDisabledMixed
- { OUT, OUT, OUT, r4, r7, r7, r7, r7, r4, OUT, OUT, OUT },
- { OUT, OUT, r7, r7, r1, r1, r1, r3, r7, r7, OUT, OUT },
- { OUT, r7, r3, r1, rW, rW, rW, rW, r1, r5, r7, OUT },
- { r4, r7, r1, rW, rW, rW, rW, rW, r1, r3, r7, r4 },
- { r7, r1, rW, rW, rW, rW, rW, r1, r1, r3, r5, r7 },
- { r7, r1, rW, r8, r8, r8, r8, r8, r8, r3, r5, r7 },
- { r7, r1, rW, r8, r8, r8, r8, r8, r8, r4, r5, r7 },
- { r7, r3, rW, rW, r1, r1, r3, r3, r4, r4, r5, r7 },
- { r4, r7, r1, r1, r1, r3, r3, r4, r4, r5, r7, r4 },
- { OUT, r7, r5, r3, r3, r3, r4, r4, r5, r5, r7, OUT },
- { OUT, OUT, r7, r7, r5, r5, r5, r5, r7, r7, OUT, OUT },
- { OUT, OUT, OUT, r4, r7, r7, r7, r7, r4, OUT, OUT, OUT },
- }
-
- };
-
- OSErr AGARadioButton::AllocateRadioImages()
- {
- // Allocate the offscreen image for each radio button state.
-
- OSErr result = noErr;
- Point imageSize;
-
- imageSize.h = kRadioImageWidth;
- imageSize.v = kRadioImageHeight;
-
- // A simple round rect defines the radio image clipping region.
-
- RgnHandle radioImageClippingRegion = ::NewRgn();
-
- if (radioImageClippingRegion == NULL)
- result = memFullErr;
- else
- {
- Rect imageClippingRect;
-
- ::SetRect(&imageClippingRect, 0, 0, kRadioImageWidth, kRadioImageHeight);
- ::OpenRgn();
- ::FrameRoundRect(&imageClippingRect, 11, 11);
- ::CloseRgn(radioImageClippingRegion);
- }
-
- for (UInt32 imageIndex = 0; imageIndex < kNumRadioImages; imageIndex++)
- {
- if (result == noErr)
- {
- mgOffscreenRadioImages[imageIndex] = new AGAOffscreenImage;
-
- result = mgOffscreenRadioImages[imageIndex]->CreateImageData(
- imageSize,
- &kRadioImageValues[imageIndex][0][0],
- radioImageClippingRegion);
- }
- }
-
- if (radioImageClippingRegion != NULL)
- ::DisposeRgn(radioImageClippingRegion);
-
- return result;
- }
-
- void AGARadioButton::DisposeRadioImages()
- {
- for (UInt32 imageIndex = 0; imageIndex < kNumRadioImages; imageIndex++)
- if (mgOffscreenRadioImages[imageIndex] != NULL)
- delete mgOffscreenRadioImages[imageIndex];
- }
-
- AGARadioButton::AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
- : AGAObject(bounds), MExclusiveObject(groupIDPart1, groupIDPart2)
- {
- // Construct with initial empty button title.
-
- mValue = kRadioButtonOff;
- mAutomaticState = automaticState;
- mTitle[0];
- mTextStyle = textStyle;
- }
-
- AGARadioButton::AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, StringPtr title, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
- : AGAObject(bounds), MExclusiveObject(groupIDPart1, groupIDPart2)
- {
- // Construct with specified button title.
-
- mValue = kRadioButtonOff;
- mAutomaticState = automaticState;
- PLstrcpy(mTitle, title);
- mTextStyle = textStyle;
- }
-
- AGARadioButton::AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
- : AGAObject(bounds), MExclusiveObject(groupIDPart1, groupIDPart2)
- {
- // Construct by getting button title from specified resource.
-
- mValue = kRadioButtonOff;
- mAutomaticState = automaticState;
- ::GetIndString(mTitle, stringListResourceID, stringIndex);
- mTextStyle = textStyle;
- }
-
- AGARadioButton::~AGARadioButton()
- {
- }
-
- void AGARadioButton::DrawObject()
- {
- // Draw button in normal unpressed state.
-
- this->DrawButton(kNotPressed);
- }
-
- Boolean AGARadioButton::TrackMouse(Point mouseLocation)
- {
- // If inherited tracking succeeded and we are set to
- // automatically change our state, toggle it.
-
- Boolean wasItHit = AGAObject::TrackMouse(mouseLocation);
-
- if (wasItHit && mAutomaticState)
- this->SetValue(kRadioButtonOn, kRedraw);
-
- return wasItHit;
- }
-
- void AGARadioButton::SetTitle(StringPtr title, Boolean redraw)
- {
- // Change button title, redraw if specified.
-
- PLstrcpy(mTitle, title);
-
- if (redraw)
- this->DrawObject();
- }
-
- SInt32 AGARadioButton::GetValue()
- {
- // Return current state.
-
- return mValue;
- }
-
- void AGARadioButton::SetValue(SInt32 newValue, Boolean redraw)
- {
- // Set current state, redraw if specified and necessary.
-
- if (newValue == kRadioButtonOn)
- gGroupsContainer->AGAHitGroupMember(this);
-
- if (newValue != mValue)
- {
- mValue = newValue;
-
- if (redraw)
- {
- this->DrawButton(kNotPressed);
- }
- }
- }
-
- void AGARadioButton::TurnOff()
- {
- // Turn off the radio button, presumably in response
- // to another button in the group being turned on.
-
- this->SetValue(kRadioButtonOff, kRedraw);
- }
-
- void AGARadioButton::DrawButton(Boolean pressed)
- {
- CleansePen();
-
- // Draw the button in the appropriate state.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (! mEnabled)
- this->DrawButtonDisabled(deep);
- else if (pressed)
- this->DrawButtonPressed(deep);
- else
- this->DrawButtonNormal(deep);
- }
-
- CleansePen();
- }
-
- void AGARadioButton::SetTrackingState(Boolean isIn)
- {
- // Draw the button pressed or unpressed as specified.
-
- this->DrawButton(isIn);
- }
-
- void AGARadioButton::DrawButtonNormal(Boolean deep)
- {
- Rect r = mBounds;
-
- // Draw the button in enabled/unpressed state.
-
- if (deep)
- {
- if (mValue == kRadioButtonMixed)
- this->CopyImage(kRadioNormalMixed);
- else if (mValue == kRadioButtonOn)
- this->CopyImage(kRadioNormalOn);
- else
- this->CopyImage(kRadioNormalOff);
- }
- else
- {
- r.right = r.left + kRadioImageWidth;
- r.bottom = r.top + kRadioImageHeight;
-
- // Paint white over previous junk, if any.
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- // Paint frame.
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameOval(&r);
-
- // Draw dot or dash.
- if (mValue == kRadioButtonOn)
- {
- ::InsetRect(&r, 3, 3);
- ::PaintRoundRect(&r, 4, 4);
- }
- else if (mValue == kRadioButtonMixed)
- {
- ::PenSize(1, 2);
- ::MoveTo(r.left + 3, r.top + 5);
- ::Line(5, 0);
- }
-
- ::PenNormal();
- }
-
- // Draw the title.
- r = mBounds;
- r.left += (kRadioImageWidth + 6);
- r.bottom = r.top + kRadioImageHeight;
- AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
- }
-
- void AGARadioButton::DrawButtonPressed(Boolean deep)
- {
- Rect r = mBounds;
-
- // Draw the button in enabled/pressed state.
-
- if (deep)
- {
- if (mValue == kRadioButtonMixed)
- this->CopyImage(kRadioPressedMixed);
- else if (mValue == kRadioButtonOn)
- this->CopyImage(kRadioPressedOn);
- else
- this->CopyImage(kRadioPressedOff);
- }
- else
- {
- r.right = r.left + kRadioImageWidth;
- r.bottom = r.top + kRadioImageHeight;
-
- // Paint white over previous junk, if any.
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- // Paint frame.
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenSize(2, 2);
- ::FrameOval(&r);
-
- // Draw check or dash.
- if (mValue == kRadioButtonOn)
- {
- ::InsetRect(&r, 3, 3);
- ::PaintRoundRect(&r, 4, 4);
- }
- else if (mValue == kRadioButtonMixed)
- {
- ::PenSize(1, 2);
- ::MoveTo(r.left + 3, r.top + 5);
- ::Line(5, 0);
- }
-
- ::PenNormal();
- }
-
- // Draw the title.
- r = mBounds;
- r.left += (kRadioImageWidth + 6);
- r.bottom = r.top + kRadioImageHeight;
- AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
- }
-
- void AGARadioButton::DrawButtonDisabled(Boolean deep)
- {
- Rect r = mBounds;
-
- // Draw the button in disabled/unpressed state.
-
- if (deep)
- {
- if (mValue == kRadioButtonMixed)
- this->CopyImage(kRadioDisabledMixed);
- else if (mValue == kRadioButtonOn)
- this->CopyImage(kRadioDisabledOn);
- else
- this->CopyImage(kRadioDisabledOff);
- }
- else
- {
- r.right = r.left + kRadioImageWidth;
- r.bottom = r.top + kRadioImageHeight;
-
- // Paint white over previous junk, if any.
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
-
- // Paint frame.
- ::PenPat(&qd.gray);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameOval(&r);
-
- // Draw check or dash.
- if (mValue == kRadioButtonOn)
- {
- ::InsetRect(&r, 3, 3);
- ::PaintRoundRect(&r, 4, 4);
- }
- else if (mValue == kRadioButtonMixed)
- {
- ::PenSize(1, 2);
- ::MoveTo(r.left + 3, r.top + 5);
- ::Line(5, 0);
- }
-
- ::PenNormal();
- }
-
- // Draw the title.
- r = mBounds;
- r.left += (kRadioImageWidth + 6);
- r.bottom = r.top + kRadioImageHeight;
- AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kDisabledOutput, deep, mTextStyle);
- }
-
- void AGARadioButton::CopyImage(UInt32 index)
- {
- // Blast the specified offscreen image into the
- // radio button's button area.
-
- mgOffscreenRadioImages[index]->DrawImage(mBounds.left, mBounds.top);
- }
-
- //
- // MIconButtonObject ---------------------------------------------------------------
- //
- // This mixin class handles button drawing for the different types
- // of icon button classes. This class draws the button, and subclasses
- // for push/radio/checkbox that mix it in handle the behavioral aspects.
- //
- // Ideal button sizes, to match AGA specification:
- // - Large icon button: 40x40 (32x32 iclx plus 4 pixel border on each side)
- // - Small icon button: 22x22 (16x16 icsx plus 3 pixel border on each side)
- // - Mini icon button: 16x16 (12x12 icmx plus 2 pixel border on each side)
- // Note that mini icons are a rather rare resource that ResEdit 2.x doesn't grok.
- //
-
- MIconButtonObject::MIconButtonObject()
- {
- // Construct with no icon IDs.
-
- mOffIconID = kNoIconID;
- mOnIconID = kNoIconID;
- mIconType = kSmallIcon;
- }
-
- MIconButtonObject::MIconButtonObject(SInt16 offIconID, SInt16 onIconID, UInt32 iconType)
- {
- // Construct with specified icon IDs.
-
- mOffIconID = offIconID;
- mOnIconID = onIconID;
- mIconType = iconType;
- }
-
- MIconButtonObject::~MIconButtonObject()
- {
- }
-
- void MIconButtonObject::SetIconIDs(SInt16 offIconID, SInt16 onIconID)
- {
- // Set icon IDs as specified.
-
- mOffIconID = offIconID;
- mOnIconID = onIconID;
- }
-
- void MIconButtonObject::SetIconType(UInt32 iconType)
- {
- // Set icon type as specified.
-
- mIconType = iconType;
- }
-
- void MIconButtonObject::DrawIconButton(Rect* bounds,
- Boolean isOn,
- Boolean isPressed,
- Boolean isEnabled,
- Boolean deep)
- {
- // Draw the icon button in the appropriate state.
-
- Rect r = *bounds;
- IconTransformType aTransform;
-
- if (deep)
- {
- if (isEnabled)
- ::RGBForeColor(&gAGARamp[rB]);
- else
- ::RGBForeColor(&gAGARamp[r8]);
-
- ::FrameRoundRect(&r, 4, 4);
-
- if (isPressed)
- {
- aTransform = ttSelected;
- ::RGBForeColor(&gAGARamp[r7]);
- }
- else if (isEnabled)
- {
- aTransform = ttNone;
-
- if (isOn)
- ::RGBForeColor(&gAGARamp[r7]);
- else
- ::RGBForeColor(&gAGARamp[r3]);
- }
- else
- {
- aTransform = ttDisabled;
-
- if (isOn)
- ::RGBForeColor(&gAGARamp[r4]);
- else
- ::RGBForeColor(&gAGARamp[r2]);
- }
-
- ::InsetRect(&r, 1, 1);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
- }
- else
- {
- if (isPressed || isOn)
- ::RGBForeColor(&gAGARamp[rB]);
- else
- ::RGBForeColor(&gAGARamp[rW]);
-
- ::PaintRoundRect(&r, 4, 4);
-
- if (! isEnabled)
- ::PenPat(&qd.gray);
-
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRoundRect(&r, 4, 4);
- ::PenNormal();
-
- if (isPressed)
- aTransform = ttSelected;
- else if (isEnabled)
- aTransform = ttNone;
- else
- aTransform = ttDisabled;
- }
-
- if (mIconType == kMiniIcon)
- this->DrawMiniEdges(bounds, isOn, isPressed, isEnabled, deep);
- else if (mIconType == kSmallIcon)
- this->DrawSmallEdges(bounds, isOn, isPressed, isEnabled, deep);
- else
- this->DrawLargeEdges(bounds, isOn, isPressed, isEnabled, deep);
-
- SInt16 halfIconSize;
- Point buttonCenter;
-
- buttonCenter.h = r.left + ((r.right - r.left) / 2);
- buttonCenter.v = r.top + ((r.bottom - r.top) / 2);
-
- if (mIconType == kMiniIcon)
- halfIconSize = 6; // 12x12 icm#
- else if (mIconType == kSmallIcon)
- halfIconSize = 8; // 16x16 ics#
- else
- halfIconSize = 16; // 32x32 icl#
-
- ::SetRect(&r, buttonCenter.h - halfIconSize,
- buttonCenter.v - halfIconSize,
- buttonCenter.h + halfIconSize,
- buttonCenter.v + halfIconSize);
-
- SInt16 iconID = isOn ? mOnIconID : mOffIconID;
-
- if (iconID != kNoIconID)
- ::PlotIconID(&r, atNone, aTransform, iconID);
- }
-
- void MIconButtonObject::DrawMiniEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled, Boolean deep)
- {
- // Draw the button edges as specified for a
- // "mini" sized button.
-
- enum { TL1, BR1, kNumEdgeColors };
-
- Rect r = *bounds;
- UInt8 colorIndexes[kNumEdgeColors];
-
- if (deep)
- {
- if (isPressed || (isEnabled && isOn))
- {
- colorIndexes[TL1] = r10;
- colorIndexes[BR1] = r5;
- }
- else if (isEnabled) // and it's off
- {
- colorIndexes[TL1] = rW;
- colorIndexes[BR1] = r6;
- }
- else if (isOn) // and it's disabled
- {
- colorIndexes[TL1] = r6;
- colorIndexes[BR1] = r2;
- }
- else // it's off and disabled
- {
- colorIndexes[TL1] = r1;
- colorIndexes[BR1] = r5;
- }
-
- ::PenSize(1, 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL1]]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR1]]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.top + 2);
- }
- else if (isPressed)
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintRoundRect(&r, 4, 4);
- }
- }
-
- void MIconButtonObject::DrawSmallEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled, Boolean deep)
- {
- // Draw the button edges as specified for a
- // "small" sized button.
-
- enum { TL1, TL2, BR1, BR2, kNumEdgeColors };
-
- Rect r = *bounds;
- UInt8 colorIndexes[kNumEdgeColors];
-
- if (deep)
- {
- if (isPressed || (isEnabled && isOn))
- {
- colorIndexes[TL1] = r11;
- colorIndexes[TL2] = r9;
- colorIndexes[BR1] = r4;
- colorIndexes[BR2] = r6;
- }
- else if (isEnabled) // and it's off
- {
- colorIndexes[TL1] = r3;
- colorIndexes[TL2] = rW;
- colorIndexes[BR1] = r8;
- colorIndexes[BR2] = r5;
- }
- else if (isOn) // and it's disabled
- {
- colorIndexes[TL1] = r6;
- colorIndexes[TL2] = r5;
- colorIndexes[BR1] = r2;
- colorIndexes[BR2] = r3;
- }
- else // it's off and disabled
- {
- colorIndexes[TL1] = r2;
- colorIndexes[TL2] = r1;
- colorIndexes[BR1] = r5;
- colorIndexes[BR2] = r4;
- }
-
- ::PenSize(1, 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL1]]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL2]]);
- ::MoveTo(r.left + 2, r.bottom - 4);
- ::LineTo(r.left + 2, r.top + 2);
- ::LineTo(r.right - 4, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR1]]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR2]]);
- ::MoveTo(r.left + 3, r.bottom - 3);
- ::LineTo(r.right - 3, r.bottom - 3);
- ::LineTo(r.right - 3, r.top + 3);
- }
- else if (isPressed)
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintRoundRect(&r, 4, 4);
- }
- }
-
- void MIconButtonObject::DrawLargeEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled, Boolean deep)
- {
- // Draw the button edges as specified for a
- // "large" sized button.
-
- enum { TL1, TL2, TL3, BR1, BR2, BR3, kNumEdgeColors };
-
- Rect r = *bounds;
- UInt8 colorIndexes[kNumEdgeColors];
-
- if (deep)
- {
- if (isPressed || (isEnabled && isOn))
- {
- colorIndexes[TL1] = r12;
- colorIndexes[TL2] = r11;
- colorIndexes[TL3] = r9;
- colorIndexes[BR1] = r4;
- colorIndexes[BR2] = r5;
- colorIndexes[BR3] = r6;
- }
- else if (isEnabled) // and it's off
- {
- colorIndexes[TL1] = r3;
- colorIndexes[TL2] = r1;
- colorIndexes[TL3] = rW;
- colorIndexes[BR1] = r11;
- colorIndexes[BR2] = r9;
- colorIndexes[BR3] = r5;
- }
- else if (isOn) // and it's disabled
- {
- colorIndexes[TL1] = r7;
- colorIndexes[TL2] = r6;
- colorIndexes[TL3] = r5;
- colorIndexes[BR1] = r1;
- colorIndexes[BR2] = r2;
- colorIndexes[BR3] = r3;
- }
- else // it's off and disabled
- {
- colorIndexes[TL1] = r3;
- colorIndexes[TL2] = r1;
- colorIndexes[TL3] = rW;
- colorIndexes[BR1] = r6;
- colorIndexes[BR2] = r5;
- colorIndexes[BR3] = r4;
- }
-
- ::PenSize(1, 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL1]]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL2]]);
- ::MoveTo(r.left + 2, r.bottom - 4);
- ::LineTo(r.left + 2, r.top + 2);
- ::LineTo(r.right - 4, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL3]]);
- ::MoveTo(r.left + 3, r.bottom - 5);
- ::LineTo(r.left + 3, r.top + 3);
- ::LineTo(r.right - 5, r.top + 3);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR1]]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR2]]);
- ::MoveTo(r.left + 3, r.bottom - 3);
- ::LineTo(r.right - 3, r.bottom - 3);
- ::LineTo(r.right - 3, r.top + 3);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR3]]);
- ::MoveTo(r.left + 4, r.bottom - 4);
- ::LineTo(r.right - 4, r.bottom - 4);
- ::LineTo(r.right - 4, r.top + 4);
- }
- else if (isPressed)
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintRoundRect(&r, 4, 4);
- }
- }
-
- UInt32 MIconButtonObject::GetDefaultIconType(SInt16 width)
- {
- if (width > 39)
- return kLargeIcon;
- else if (width > 21)
- return kSmallIcon;
- else
- return kMiniIcon;
- }
-
-
- //
- // AGAIconPushButton ---------------------------------------------------------------
- //
- // This class implements an icon-based pushbutton object, such as
- // a toolbar icon command button.
- //
-
- AGAIconPushButton::AGAIconPushButton(Rect* bounds)
- : AGAPushButton(bounds, gAGAStdSystemStyle), MIconButtonObject()
- {
- // Just call through to mixed in constructors.
- }
-
- AGAIconPushButton::AGAIconPushButton(Rect* bounds, SInt16 iconID, UInt32 iconType)
- : AGAPushButton(bounds, gAGAStdSystemStyle), MIconButtonObject(iconID, iconID, iconType)
- {
- // Just call through to mixed in constructors.
- }
-
- AGAIconPushButton::~AGAIconPushButton()
- {
- }
-
- void AGAIconPushButton::DrawButtonNormal(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, FALSE, kNotPressed, kEnabled, deep);
- }
-
- void AGAIconPushButton::DrawButtonPressed(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, FALSE, kPressed, kEnabled, deep);
- }
-
- void AGAIconPushButton::DrawButtonDisabled(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, FALSE, kNotPressed, kDisabled, deep);
- }
-
- //
- // AGAIconCheckBox ---------------------------------------------------------------
- //
- // This class implements an icon-based checkbox object, such as
- // a toolbar icon on/off button.
- //
-
- AGAIconCheckBox::AGAIconCheckBox(Rect* bounds, Boolean automaticState)
- : AGACheckBox(bounds, gAGAStdSystemStyle, automaticState), MIconButtonObject()
- {
- // Just call through to mixed in constructors.
- }
-
- AGAIconCheckBox::AGAIconCheckBox(Rect* bounds, Boolean automaticState, SInt16 offIconID, SInt16 onIconID, UInt32 iconType)
- : AGACheckBox(bounds, gAGAStdSystemStyle, automaticState), MIconButtonObject(offIconID, onIconID, iconType)
- {
- // Just call through to mixed in constructors.
- }
-
- AGAIconCheckBox::~AGAIconCheckBox()
- {
- }
-
- void AGAIconCheckBox::DrawButtonNormal(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, mValue != kCheckBoxOff, kNotPressed, kEnabled, deep);
- }
-
- void AGAIconCheckBox::DrawButtonPressed(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, mValue != kCheckBoxOff, kPressed, kEnabled, deep);
- }
-
- void AGAIconCheckBox::DrawButtonDisabled(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, mValue != kCheckBoxOff, kNotPressed, kDisabled, deep);
- }
-
- //
- // AGAIconRadioButton ---------------------------------------------------------------
- //
- // This class implements an icon-based pushbutton object, such as
- // a toolbar icon XOR group member button.
- //
-
- AGAIconRadioButton::AGAIconRadioButton(Rect* bounds, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
- : AGARadioButton(bounds, gAGAStdSystemStyle, groupIDPart1, groupIDPart2, automaticState), MIconButtonObject()
- {
- // Just call through to mixed in constructors.
- }
-
- AGAIconRadioButton::AGAIconRadioButton(Rect* bounds, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState, SInt16 offIconID, SInt16 onIconID, UInt32 iconType)
- : AGARadioButton(bounds, gAGAStdSystemStyle, groupIDPart1, groupIDPart2, automaticState), MIconButtonObject(offIconID, onIconID, iconType)
- {
- // Just call through to mixed in constructors.
- }
-
- AGAIconRadioButton::~AGAIconRadioButton()
- {
- }
-
- void AGAIconRadioButton::DrawButtonNormal(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, mValue != kRadioButtonOff, kNotPressed, kEnabled, deep);
- }
-
- void AGAIconRadioButton::DrawButtonPressed(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, mValue != kRadioButtonOff, kPressed, kEnabled, deep);
- }
-
- void AGAIconRadioButton::DrawButtonDisabled(Boolean deep)
- {
- // Call icon button parent class with appropriate parameters.
-
- MIconButtonObject::DrawIconButton(&mBounds, mValue != kRadioButtonOff, kNotPressed, kDisabled, deep);
- }
-
- //
- // AGATrackingIndicator ---------------------------------------------------------------
- //
- // This is the abstract superclass for scroll bars and sliders.
- // They all have a range, and a value shown by a draggable indicator.
- //
-
- #pragma segment GrayCouncilCore2
-
- AGATrackingIndicator::AGATrackingIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue)
- : AGAObject(bounds)
- {
- // Construct with default options.
-
- mMinimum = minimum;
- mMaximum = maximum;
- mValue = initialValue;
-
- mPageSize = 1;
- mGhostValue = mValue;
- mLiveTracking = FALSE;
- mIsProportional = FALSE;
- mIsHorizontal = (bounds->right - bounds->left) > (bounds->bottom - bounds->top);
- mIsPressed = FALSE;
-
- mNotificationRoutine = NULL;
- }
-
- AGATrackingIndicator::AGATrackingIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, SInt32 pageSize, Boolean liveTracking, Boolean proportional)
- : AGAObject(bounds)
- {
- // Construct with specified options.
-
- mMinimum = minimum;
- mMaximum = maximum;
- mValue = initialValue;
- mPageSize = pageSize;
- mGhostValue = mValue;
- mLiveTracking = liveTracking;
- mIsProportional = proportional;
- mIsHorizontal = (bounds->right - bounds->left) > (bounds->bottom - bounds->top);
- mIsPressed = FALSE;
-
- mNotificationRoutine = NULL;
- }
-
- AGATrackingIndicator::~AGATrackingIndicator()
- {
- }
-
- void AGATrackingIndicator::InstallNotificationRoutine(AGATrackingIndicatorNotifyPtr notificationRoutine, void* userData)
- {
- // Install the supplied function pointer and user data to
- // be called during notification.
-
- mNotificationRoutine = notificationRoutine;
- mUserData = userData;
- }
-
- void AGATrackingIndicator::SetAttributes(Boolean isHorizontal, Boolean liveTracking, Boolean isProportional)
- {
- // Set options as specified.
-
- mIsHorizontal = isHorizontal;
- mLiveTracking = liveTracking;
- mIsProportional = isProportional;
- }
-
- void AGATrackingIndicator::DrawObject()
- {
- // Call component drawing functions. These are all overridden
- // by subclasses.
-
- this->DrawBackground();
- this->DrawIndicatorTrack();
- this->DrawTrackEnds();
- this->DrawIndicator();
- }
-
- Boolean AGATrackingIndicator::TrackMouse(Point mouseLocation)
- {
- // Track the mouse and return true if the indicator
- // value was changed.
-
- return this->TrackPart(mouseLocation, this->TrackTestPart(mouseLocation));
- }
-
- Boolean AGATrackingIndicator::TrackPart(Point mouseLocation, SInt32 partHit)
- {
- // Track the mouse in the specified part and return true
- // if the indicator value was changed.
-
- if (partHit != kIndicatorPress)
- return FALSE;
-
- SInt32 originalValue = mValue;
- Point oldPoint = mouseLocation;
- Point newPoint = mouseLocation;
- SInt32 oldValue = originalValue;
- SInt32 newValue = originalValue;
- Boolean isButtonDown = TRUE; // ensure at least one time through
-
- mGhostValue = mValue;
- mIsPressed = TRUE;
- this->DrawIndicator(); // will draw it pressed
-
- while (isButtonDown)
- {
- ::GetMouse(&newPoint); // gives local coordinates
-
- if (this->IsValidIndicatorTrackMouse(newPoint) &&
- ! ::EqualPt(newPoint, oldPoint))
- {
- newValue = this->GetValueFromMouseDelta(oldValue, mouseLocation, newPoint);
-
- if (mLiveTracking)
- {
- SInt32 oldValue = mValue;
-
- this->SetValue(newValue, kRedraw);
-
- if (mValue != oldValue)
- this->NotifyValue();
- }
- else
- this->SetGhostValue(newValue, kRedraw);
-
- oldPoint = newPoint;
- }
-
- isButtonDown = ::StillDown();
- }
-
- mIsPressed = FALSE;
-
- if (mLiveTracking)
- this->DrawIndicator(); // unpressed
- else
- {
- this->RemoveGhost(newValue);
- this->DrawIndicator(); // unpressed
-
- if (newValue != mValue) // don't notify if no change
- {
- this->SetValue(newValue, kRedraw); // will draw new indicator
- this->NotifyValue();
- }
- }
-
- return (mValue != originalValue);
- }
-
- SInt32 AGATrackingIndicator::GetValue()
- {
- // Return the current indicator value.
-
- return mValue;
- }
-
- void AGATrackingIndicator::SetGhostValue(SInt32 newValue, Boolean redraw)
- {
- // Set the ghost indicator value, and optionally redraw it
- // at its new position.
-
- if (newValue > mMaximum)
- newValue = mMaximum;
- else if (newValue < mMinimum)
- newValue = mMinimum;
-
- if (newValue != mGhostValue)
- {
- if (redraw)
- this->RemoveGhost(newValue);
-
- mGhostValue = newValue;
-
- if (redraw)
- this->DrawGhost();
- }
- }
-
- void AGATrackingIndicator::SetValue(SInt32 newValue, Boolean redraw)
- {
- // Set the indicator value, and optionally redraw it
- // at its new position.
-
- if (newValue > mMaximum)
- newValue = mMaximum;
- else if (newValue < mMinimum)
- newValue = mMinimum;
-
- if (newValue != mValue)
- {
- if (redraw)
- this->RemoveIndicator(newValue);
-
- mValue = newValue;
-
- if (redraw)
- this->DrawIndicator();
- }
- }
-
- void AGATrackingIndicator::GetRange(SInt32* minimum, SInt32* maximum)
- {
- // Return the current min/max range.
-
- *minimum = mMinimum;
- *maximum = mMaximum;
- }
-
- void AGATrackingIndicator::SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw)
- {
- // Set the min/max range, and optionally redraw.
-
- if ((newMinimum != mMinimum) ||
- (newMaximum != mMaximum))
- {
- if (redraw)
- this->RemoveIndicator(mValue);
-
- mMinimum = newMinimum;
- mMaximum = newMaximum;
-
- if (redraw)
- this->DrawIndicator();
- }
- }
-
- SInt32 AGATrackingIndicator::GetPageSize()
- {
- // Return the current indicator page size.
-
- return mPageSize;
- }
-
- void AGATrackingIndicator::SetPageSize(SInt32 newPageSize, Boolean redraw)
- {
- // Set the indicator page size. Redraw is not
- // necessary if the indicator is not proportional.
-
- if (newPageSize != mPageSize)
- {
- if (redraw && mIsProportional)
- this->RemoveIndicator(mValue);
-
- mPageSize = newPageSize;
-
- if (redraw && mIsProportional)
- this->DrawIndicator();
- }
- }
-
- SInt32 AGATrackingIndicator::TrackTestPart(Point mouseLocation)
- {
- // Must be overridden. Return the part value that the
- // specified mouse position would hit.
-
- return kNoTrackPress;
- }
-
- Boolean AGATrackingIndicator::IsValidIndicatorTrackMouse(Point mouseLocation)
- {
- // Usually overridden. Return true if the specified mouse
- // position should be considered "in" for tracking purposes
- // after the initial hit has succeeded. Return false if the
- // specified mouse position is too far away from the control
- // to use it for the next momentary tracking position.
-
- return ::PtInRect(mouseLocation, &mBounds);
- }
-
- SInt32 AGATrackingIndicator::GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation)
- {
- // Must be overridden. Return the indicator value that should be
- // applied assuming the supplied starting value and mouse hit point,
- // and the supplied current mouse tracking location.
- return originalValue;
- }
-
- void AGATrackingIndicator::DrawBackground()
- {
- // Override to paint the background area so that the
- // indicator drawn at its old position will be wiped out.
- // Clipping will be already set up to avoid excess flicker.
- }
-
- void AGATrackingIndicator::DrawIndicatorTrack()
- {
- // Override to draw the empty indicator track. Must include
- // all possible indicator coverage.
- }
-
- void AGATrackingIndicator::DrawTrackEnds()
- {
- // Override to draw the track ends outside the possible
- // indicator coverage if not drawn in DrawIndicatorTrack.
- }
-
- void AGATrackingIndicator::DrawIndicator()
- {
- // Override to draw the indicator at its current value/state.
- }
-
- void AGATrackingIndicator::RemoveIndicator(SInt32 newValue)
- {
- // Override to draw/erase whatever is needed to remove the
- // current indicator in preparation for being drawn at
- // the specified new value. The new value is supplied so
- // that erasing can be kept to a minimal area.
- }
-
- void AGATrackingIndicator::DrawGhost()
- {
- // Override to draw the indicator in ghost mode at
- // the current ghost value.
- }
-
- void AGATrackingIndicator::RemoveGhost(SInt32 newValue)
- {
- // Override to draw/erase whatever is needed to remove the
- // ghost indicator in preparation for being drawn at
- // the specified new value. The new value is supplied so
- // that erasing can be kept to a minimal area.
- }
-
- void AGATrackingIndicator::NotifyValue()
- {
- // Call the installed notification routine, if any, with
- // the installed user data and our new value.
-
- if (mNotificationRoutine != NULL)
- (*(mNotificationRoutine))(this, mValue, mUserData);
- }
-
- //
- // AGAScrollBar ---------------------------------------------------------------
- //
- // This class implements a standard AGA scroll bar, with the additional
- // ability to perform live tracking and a proportional thumb.
- //
-
- // These regions are used momentarily while tracking the scroll
- // bar indicator to clip and optimize redrawing.
- RgnHandle AGAScrollBar::mgSavedIndicatorClip = ::NewRgn();
- RgnHandle AGAScrollBar::mgOldIndicatorClip = ::NewRgn();
- RgnHandle AGAScrollBar::mgNewIndicatorClip = ::NewRgn();
-
- AGAScrollBar::AGAScrollBar(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue)
- : AGATrackingIndicator(bounds, minimum, maximum, initialValue)
- {
- // Construct with default options.
- mLiveTracking = TestGrayCouncilDefault(kAGALiveScrolling);
- mIsProportional = TestGrayCouncilDefault(kAGAProportionalScrolling);
-
- mSingleStepSize = 1;
- mPageStepSize = 1;
- mActive = TRUE;
- }
-
- AGAScrollBar::AGAScrollBar(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, SInt32 singleStepSize, SInt32 pageStepSize, SInt32 pageSize, Boolean liveTracking, Boolean proportional)
- : AGATrackingIndicator(bounds, minimum, maximum, initialValue, pageSize, liveTracking, proportional)
- {
- // Construct with specified options.
-
- mSingleStepSize = singleStepSize;
- mPageStepSize = pageStepSize;
- mActive = TRUE;
- }
-
- AGAScrollBar::~AGAScrollBar()
- {
- }
-
- void AGAScrollBar::SetStepSizes(SInt32 singleStepSize, SInt32 pageStepSize)
- {
- // Set the scrolling step delta amounts.
-
- mSingleStepSize = singleStepSize;
- mPageStepSize = pageStepSize;
- }
-
- void AGAScrollBar::Activate(Boolean activateState, Boolean redraw)
- {
- // Set the active/inactive state. Scroll bars are the
- // only control that have a different appearance when
- // in an inactive window.
-
- mActive = activateState;
-
- if (redraw)
- this->DrawObject();
- }
-
- Boolean AGAScrollBar::TrackPart(Point mouseLocation, SInt32 partHit)
- {
- // Track the mouse and return true if tracking changed the
- // indicator value. Thumb tracking is handled by superclass.
- // Scroll bar just handles arrow and page tracking.
-
- if ((partHit != kArrowMinusPress) && (partHit != kArrowPlusPress) &&
- (partHit != kPageMinusPress) && (partHit != kPagePlusPress))
- return AGATrackingIndicator::TrackPart(mouseLocation, partHit);
-
- Boolean wasIn = FALSE;
- Boolean isIn = TRUE;
- Boolean isButtonDown = TRUE; // ensure at least one time through
- Point newMouseLocation;
- UInt32 accelerationDelay = 18; // will divide by 2 each time
-
- while (isButtonDown)
- {
- if (isIn)
- this->TrackDelta(partHit);
-
- ::GetMouse(&newMouseLocation); // gives local coordinates
-
- isIn = (this->TrackTestPart(newMouseLocation) == partHit);
-
- if (isIn != wasIn)
- this->DrawArrow(partHit, isIn);
-
- wasIn = isIn;
-
- if (isButtonDown && (accelerationDelay != 0))
- {
- DelayFutureWhileStillDown(accelerationDelay);
- accelerationDelay = accelerationDelay >> 1; // divide by 2
- }
-
- isButtonDown = ::StillDown();
- }
-
- if (isIn) // if finished IN, restore normal appearance
- this->DrawArrow(partHit, kNotPressed);
-
- return TRUE;
- }
-
- SInt32 AGAScrollBar::TrackTestPart(Point mouseLocation)
- {
- // Return the part value that the specified mouse
- // position would hit.
-
- Rect arrowMinusRect = mBounds;
- Rect arrowPlusRect = mBounds;
- Rect pageMinusRect = mBounds;
- Rect pagePlusRect = mBounds;
- Rect indicatorRect;
-
- this->GetIndicatorBox(mValue, &indicatorRect);
-
- if (mIsHorizontal)
- {
- arrowPlusRect.left = arrowPlusRect.right - kArrowSize;
- arrowMinusRect.right = arrowMinusRect.left + kArrowSize;
-
- pageMinusRect.left = arrowMinusRect.right;
- pageMinusRect.right = indicatorRect.left;
-
- pagePlusRect.left = indicatorRect.right;
- pagePlusRect.right = arrowPlusRect.left;
- }
- else
- {
- arrowPlusRect.top = arrowPlusRect.bottom - kArrowSize;
- arrowMinusRect.bottom = arrowMinusRect.top + kArrowSize;
-
- pageMinusRect.top = arrowMinusRect.bottom;
- pageMinusRect.bottom = indicatorRect.top;
-
- pagePlusRect.top = indicatorRect.bottom;
- pagePlusRect.bottom = arrowPlusRect.top;
- }
-
- if (::PtInRect(mouseLocation, &arrowMinusRect))
- return kArrowMinusPress;
- else if (::PtInRect(mouseLocation, &arrowPlusRect))
- return kArrowPlusPress;
- else if (::PtInRect(mouseLocation, &pageMinusRect))
- return kPageMinusPress;
- else if (::PtInRect(mouseLocation, &pagePlusRect))
- return kPagePlusPress;
- else if (::PtInRect(mouseLocation, &indicatorRect))
- return kIndicatorPress;
- else
- return kNoTrackPress;
- }
-
- Boolean AGAScrollBar::IsValidIndicatorTrackMouse(Point mouseLocation)
- {
- // Return true if the mouse is reasonably near
- // the track.
-
- Rect okRect = mBounds;
-
- ::InsetRect(&okRect, -32, -32); // slop for mouse tracking
-
- return ::PtInRect(mouseLocation, &okRect);
- }
-
- SInt32 AGAScrollBar::GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation)
- {
- // Return the new indicator value based on the mouse delta
- // from the original mouse location and indicator value.
-
- SInt32 dontCare;
- SInt32 valueRange = mMaximum - mMinimum;
- SInt32 pixelRange = this->GetIndicatorPixelRange(&dontCare);
- SInt32 pixelDelta;
- float pixelFraction;
-
- if (mIsHorizontal)
- pixelDelta = newMouseLocation.h - originalMouseLocation.h;
- else
- pixelDelta = newMouseLocation.v - originalMouseLocation.v;
-
- pixelFraction = ((float) pixelDelta) / (float) pixelRange;
-
- float delta = pixelFraction * ((float) valueRange);
- delta += (float) 0.5; // round to nearest integer, don't just truncate fraction
-
- return originalValue + delta;
- }
-
- void AGAScrollBar::DrawIndicatorTrack()
- {
- CleansePen();
-
- // Draw the empty scroll bar track.
-
- GDIterator iter;
- Boolean deep;
-
- Boolean enabled = mEnabled && (mMaximum > mMinimum);
-
- while (iter.More(deep))
- {
- if (deep)
- {
- Rect r = mBounds;
-
- if (mActive)
- ::RGBForeColor(&gAGARamp[rB]);
- else
- ::RGBForeColor(&gAGARamp[r10]);
-
- ::FrameRect(&r);
-
- if (mIsHorizontal)
- ::InsetRect(&r, kArrowSize - 1, 0);
- else
- ::InsetRect(&r, 0, kArrowSize - 1);
-
- if ((! mActive) || (! enabled))
- {
- ::RGBForeColor(&gAGARamp[r1]);
- ::InsetRect(&r, 1, 1);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- if (mActive)
- ::RGBForeColor(&gAGARamp[r8]);
-
- if (mIsHorizontal)
- {
- ::MoveTo(r.left, r.top + 1);
- ::LineTo(r.left, r.bottom - 2);
- ::MoveTo(r.right - 1, r.top + 1);
- ::LineTo(r.right - 1, r.bottom - 2);
- }
- else
- {
- ::MoveTo(r.left + 1, r.top);
- ::LineTo(r.right - 2, r.top);
- ::MoveTo(r.left + 1, r.bottom - 1);
- ::LineTo(r.right - 2, r.bottom - 1);
- }
- }
- else // enabled
- {
- ::RGBForeColor(&gAGARamp[r5]);
- ::InsetRect(&r, 1, 1);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- ::RGBForeColor(&gAGARamp[rB]);
-
- if (mIsHorizontal)
- {
- ::MoveTo(r.left, r.top + 1);
- ::LineTo(r.left, r.bottom - 2);
- ::MoveTo(r.right - 1, r.top + 1);
- ::LineTo(r.right - 1, r.bottom - 2);
-
- // Draw the shadowing.
-
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 2, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.left + 2, r.bottom - 4);
- ::LineTo(r.left + 2, r.top + 2);
- ::LineTo(r.right - 3, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[r3]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.bottom - 2);
-
- ::RGBForeColor(&gAGARamp[r4]);
- ::MoveTo(r.left + 3, r.bottom - 3);
- ::LineTo(r.right - 2, r.bottom - 3);
- }
- else
- {
- ::MoveTo(r.left + 1, r.top);
- ::LineTo(r.right - 2, r.top);
- ::MoveTo(r.left + 1, r.bottom - 1);
- ::LineTo(r.right - 2, r.bottom - 1);
-
- // Draw the shadowing.
-
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left + 1, r.bottom - 2);
- ::LineTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.left + 2, r.top + 2);
- ::LineTo(r.right - 4, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[r3]);
- ::MoveTo(r.right - 2, r.top + 2);
- ::LineTo(r.right - 2, r.bottom - 2);
-
- ::RGBForeColor(&gAGARamp[r4]);
- ::MoveTo(r.right - 3, r.top + 3);
- ::LineTo(r.right - 3, r.bottom - 2);
- }
- }
- }
- else // 1-bit
- {
- Rect r = mBounds;
-
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&mBounds);
-
- if (enabled && mActive)
- {
- if (mIsHorizontal)
- {
- ::InsetRect(&r, kArrowSize - 1, 0);
- ::MoveTo(r.left, r.top + 1);
- ::LineTo(r.left, r.bottom - 2);
- ::MoveTo(r.right - 1, r.top + 1);
- ::LineTo(r.right - 1, r.bottom - 2);
- }
- else
- {
- ::InsetRect(&r, 0, kArrowSize - 1);
- ::MoveTo(r.left + 1, r.top);
- ::LineTo(r.right - 2, r.top);
- ::MoveTo(r.left + 1, r.bottom - 1);
- ::LineTo(r.right - 2, r.bottom - 1);
- }
- }
- }
- }
-
- CleansePen();
- }
-
- void AGAScrollBar::DrawTrackEnds()
- {
- CleansePen();
-
- // Draw the scroll arrows.
-
- this->DrawArrow(kArrowMinusPress, kNotPressed);
- this->DrawArrow(kArrowPlusPress, kNotPressed);
-
- CleansePen();
- }
-
- void AGAScrollBar::DrawIndicator()
- {
- CleansePen();
-
- // Draw the thumb indicator.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- Boolean enabled = mEnabled && (mMaximum > mMinimum);
-
- if ((! enabled) || (! mActive))
- return;
-
- enum { Fill, Light, TL, BR, Dark, kIndicatorColors };
-
- UInt8 colorIndexes[kIndicatorColors];
- Rect r = mBounds;
- SInt32 startPt;
- SInt32 valuePt;
- SInt32 stopPt;
- Point drawDirection;
- Point moveDirection;
- SInt16 lineLength;
-
- if (deep)
- {
- if (mIsPressed)
- {
- colorIndexes[Fill] = r8;
- colorIndexes[Light] = r3;
- colorIndexes[TL] = r5;
- colorIndexes[BR] = r10;
- colorIndexes[Dark] = r12;
- }
- else
- {
- colorIndexes[Fill] = r5;
- colorIndexes[Light] = r1;
- colorIndexes[TL] = r3;
- colorIndexes[BR] = r8;
- colorIndexes[Dark] = r10;
- }
- }
- else
- {
- if (mIsPressed)
- {
- colorIndexes[Fill] = rB;
- colorIndexes[Light] = rB;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = rB;
- colorIndexes[Dark] = rB;
- }
- else
- {
- colorIndexes[Fill] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rB;
- colorIndexes[BR] = rW;
- colorIndexes[Dark] = rW;
- }
- }
-
- this->GetIndicatorSpan(mValue, &startPt, &valuePt, &stopPt);
- this->GetIndicatorBox(mValue, &r);
-
- if (mIsHorizontal)
- {
- ::SetPt(&drawDirection, 0, 1);
- ::SetPt(&moveDirection, 1, 0);
- lineLength = r.bottom - r.top - 11;
- }
- else
- {
- ::SetPt(&drawDirection, 1, 0);
- ::SetPt(&moveDirection, 0, 1);
- lineLength = r.right - r.left - 11;
- }
-
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
- ::InsetRect(&r, 1, 1);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- if (deep)
- {
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 2);
- ::Move(1, -1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::MoveTo(r.right - 2, r.top + 2);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.left + 2, r.bottom - 2);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
- ::MoveTo(r.left + 1, r.top + 1);
- ::Line(0, 0);
- }
-
- ::MoveTo(r.left + 4 + (moveDirection.h * (((r.right - r.left) / 2) - 8)),
- r.top + 4 + (moveDirection.v * (((r.bottom - r.top) / 2) - 8)));
-
- if (! deep)
- ::Move(moveDirection.h, moveDirection.v);
-
- for (SInt32 i = 0; i < 4; i++)
- {
- ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
- ::Line(0, 0);
-
- ::Move(drawDirection.h, drawDirection.v);
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::Line(drawDirection.h * lineLength, drawDirection.v * lineLength);
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(drawDirection.h, drawDirection.v);
- ::RGBForeColor(&gAGARamp[colorIndexes[Dark]]);
- ::Line(- (drawDirection.h * (lineLength+1)), - (drawDirection.v * (lineLength+1)));
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(- drawDirection.h, - drawDirection.v);
- }
- }
-
- CleansePen();
- }
-
- void AGAScrollBar::RemoveIndicator(SInt32 newValue)
- {
- CleansePen();
-
- // Draw the track/background to remove the current
- // indicator.
-
- //
- // Set clipping so we only draw the track to
- // wipe out the old indicator, but not where
- // the new indicator will get drawn anyway.
- // This reduces flicker.
- //
-
- ::GetClip(mgSavedIndicatorClip);
-
- if (newValue != mValue)
- {
- Rect oldIndicatorBox;
- Rect newIndicatorBox;
-
- this->GetIndicatorBox(mValue, &oldIndicatorBox);
- this->GetIndicatorBox(newValue, &newIndicatorBox);
-
- ::RectRgn(mgOldIndicatorClip, &oldIndicatorBox);
- ::RectRgn(mgNewIndicatorClip, &newIndicatorBox);
- ::DiffRgn(mgOldIndicatorClip, mgNewIndicatorClip, mgOldIndicatorClip);
-
- ::SetClip(mgOldIndicatorClip);
- }
-
- this->DrawIndicatorTrack();
-
- ::SetClip(mgSavedIndicatorClip);
-
- CleansePen();
- }
-
- void AGAScrollBar::DrawGhost()
- {
- CleansePen();
-
- // Draw the indicator as a ghost at the current mGhostValue
- // position.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- Rect r = mBounds;
- SInt32 startPt;
- SInt32 valuePt;
- SInt32 stopPt;
- Point drawDirection;
- Point moveDirection;
- SInt16 lineLength;
-
- this->GetIndicatorSpan(mGhostValue, &startPt, &valuePt, &stopPt);
- this->GetIndicatorBox(mGhostValue, &r);
-
- if (deep)
- {
- if (mIsHorizontal)
- {
- ::SetPt(&drawDirection, 0, 1);
- ::SetPt(&moveDirection, 1, 0);
- lineLength = r.bottom - r.top - 11;
-
- ::RGBForeColor(&gAGARamp[r4]);
- ::InsetRect(&r, 1, 3);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -3);
-
- ::RGBForeColor(&gAGARamp[r11]);
- ::MoveTo(r.left, r.top + 1);
- ::Line(0, 0);
- ::MoveTo(r.right - 1, r.top + 1);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.left, r.top + 2);
- ::Line(0, 0);
- ::MoveTo(r.right - 1, r.top + 2);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left, r.top + 3);
- ::LineTo(r.left, r.bottom - 4);
- ::MoveTo(r.right - 1, r.top + 3);
- ::LineTo(r.right - 1, r.bottom - 4);
-
- ::RGBForeColor(&gAGARamp[r6]);
- ::MoveTo(r.left, r.bottom - 3);
- ::Line(0, 0);
- ::MoveTo(r.right - 1, r.bottom - 3);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r4]);
- ::MoveTo(r.left, r.bottom - 2);
- ::Line(0, 0);
- ::MoveTo(r.right - 1, r.bottom - 2);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r6]);
- ::MoveTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 2, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.left + 1, r.top + 2);
- ::LineTo(r.right - 2, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[r3]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.right - 2, r.bottom - 3);
-
- ::RGBForeColor(&gAGARamp[r2]);
- ::MoveTo(r.left + 1, r.bottom - 2);
- ::LineTo(r.right - 2, r.bottom - 2);
- }
- else
- {
- ::SetPt(&drawDirection, 1, 0);
- ::SetPt(&moveDirection, 0, 1);
- lineLength = r.right - r.left - 11;
-
- ::RGBForeColor(&gAGARamp[r4]);
- ::InsetRect(&r, 3, 1);
- ::PaintRect(&r);
- ::InsetRect(&r, -3, -1);
-
- ::RGBForeColor(&gAGARamp[r11]);
- ::MoveTo(r.left + 1, r.top);
- ::Line(0, 0);
- ::MoveTo(r.left + 1, r.bottom - 1);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.left + 2, r.top);
- ::Line(0, 0);
- ::MoveTo(r.left + 2, r.bottom - 1);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left + 3, r.top);
- ::LineTo(r.right - 4, r.top);
- ::MoveTo(r.left + 3, r.bottom - 1);
- ::LineTo(r.right - 4, r.bottom - 1);
-
- ::RGBForeColor(&gAGARamp[r6]);
- ::MoveTo(r.right - 3, r.top);
- ::Line(0, 0);
- ::MoveTo(r.right - 3, r.bottom - 1);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r4]);
- ::MoveTo(r.right - 2, r.top);
- ::Line(0, 0);
- ::MoveTo(r.right - 2, r.bottom - 1);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[r6]);
- ::MoveTo(r.left + 1, r.top + 1);
- ::LineTo(r.left + 1, r.bottom - 2);
-
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.left + 2, r.top + 1);
- ::LineTo(r.left + 2, r.bottom - 2);
-
- ::RGBForeColor(&gAGARamp[r3]);
- ::MoveTo(r.right - 3, r.top + 1);
- ::LineTo(r.right - 3, r.bottom - 2);
-
- ::RGBForeColor(&gAGARamp[r2]);
- ::MoveTo(r.right - 2, r.top + 1);
- ::LineTo(r.right - 2, r.bottom - 2);
- }
-
- ::MoveTo(r.left + 4 + (moveDirection.h * (((r.right - r.left) / 2) - 8)),
- r.top + 4 + (moveDirection.v * (((r.bottom - r.top) / 2) - 8)));
-
- for (SInt32 i = 0; i < 4; i++)
- {
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(drawDirection.h * (lineLength+1), drawDirection.v * (lineLength+1));
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(drawDirection.h, drawDirection.v);
- ::RGBForeColor(&gAGARamp[r6]);
- ::Line(- (drawDirection.h * (lineLength+1)), - (drawDirection.v * (lineLength+1)));
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(- drawDirection.h, - drawDirection.v);
- }
- }
- else
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
- }
- }
-
- CleansePen();
- }
-
- void AGAScrollBar::RemoveGhost(SInt32 newValue)
- {
- CleansePen();
-
- // Draw the track/background to remove the current
- // ghost indicator.
-
- Rect r;
- RgnHandle savedClip = ::NewRgn();
-
- ::GetClip(savedClip);
-
- this->GetIndicatorBox(mGhostValue, &r);
- ::ClipRect(&r);
- this->DrawIndicatorTrack();
- this->DrawIndicator();
-
- ::SetClip(savedClip);
-
- CleansePen();
- }
-
- void AGAScrollBar::TrackDelta(SInt32 partHit)
- {
- // Change our value based on the delta amount
- // for the part that was hit. Do notification
- // of the value change.
-
- SInt32 oldValue = mValue;
- SInt32 newValue = mValue;
-
- switch (partHit)
- {
- case kPageMinusPress:
- newValue -= mPageStepSize;
- break;
- case kArrowMinusPress:
- newValue -= mSingleStepSize;
- break;
- case kArrowPlusPress:
- newValue += mSingleStepSize;
- break;
- case kPagePlusPress:
- newValue += mPageStepSize;
- break;
- }
-
- this->SetValue(newValue, kRedraw);
-
- if (mValue != oldValue)
- this->NotifyValue();
- }
-
- void AGAScrollBar::DrawArrow(SInt32 arrowPart, Boolean pressed)
- {
- CleansePen();
-
- // Draw the specified arrow in the specified mode.
-
- Boolean enabled = mEnabled && (mMaximum > mMinimum);
-
- if ((arrowPart != kArrowMinusPress) &&
- (arrowPart != kArrowPlusPress))
- return;
-
- enum { Fill, TL, BR, Arrow, kNumArrowColors };
-
- UInt8 colorIndexes[kNumArrowColors];
- Rect r = mBounds;
-
- if (mIsHorizontal)
- {
- if (arrowPart == kArrowPlusPress)
- r.left = r.right - kArrowSize;
- else
- r.right = r.left + kArrowSize;
- }
- else
- {
- if (arrowPart == kArrowPlusPress)
- r.top = r.bottom - kArrowSize;
- else
- r.bottom = r.top + kArrowSize;
- }
-
- // Note: we don't draw the outer frame.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- if (! mActive)
- {
- colorIndexes[Fill] = r1;
- colorIndexes[TL] = r1;
- colorIndexes[BR] = r1;
- colorIndexes[Arrow] = r1;
- }
- else if (pressed)
- {
- colorIndexes[Fill] = r8;
- colorIndexes[TL] = r10;
- colorIndexes[BR] = r6;
- colorIndexes[Arrow] = rB;
- }
- else if (enabled)
- {
- colorIndexes[Fill] = r2;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = r5;
- colorIndexes[Arrow] = rB;
- }
- else // disabled
- {
- colorIndexes[Fill] = r2;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = r4;
- colorIndexes[Arrow] = r8;
- }
- }
- else
- {
- if ((! mActive) || ! enabled)
- {
- colorIndexes[Fill] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = rW;
- colorIndexes[Arrow] = rW;
- }
- else if (pressed)
- {
- colorIndexes[Fill] = rB;
- colorIndexes[TL] = rB;
- colorIndexes[BR] = rB;
- colorIndexes[Arrow] = rW;
- }
- else // unpressed + enabled
- {
- colorIndexes[Fill] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = rW;
- colorIndexes[Arrow] = rB;
- }
- }
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
- ::InsetRect(&r, 1, 1);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::MoveTo(r.right - 2, r.top + 2);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.left + 2, r.bottom - 2);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Arrow]]);
- SInt16 direction = (arrowPart == kArrowPlusPress) ? 1 : -1;
- SInt16 offset = (arrowPart == kArrowPlusPress) ? 6 : 9;
-
- if (mIsHorizontal)
- {
- ::MoveTo(r.left + offset, ((r.top + r.bottom) / 2) - 4);
- ::Line(0, 7);
- ::Move(direction, -6);
- ::Line(0, 5);
- ::Move(direction, -4);
- ::Line(0, 3);
- ::Move(direction, -2);
- ::Line(0, 1);
- }
- else
- {
- ::MoveTo(((r.left + r.right) / 2) - 4, r.top + offset);
- ::Line(7, 0);
- ::Move(-6, direction);
- ::Line(5, 0);
- ::Move(-4, direction);
- ::Line(3, 0);
- ::Move(-2, direction);
- ::Line(1, 0);
- }
- }
-
- CleansePen();
- }
-
- void AGAScrollBar::GetIndicatorBox(SInt32 indicatorValue, Rect* indicatorBox)
- {
- // Return the bounds of the indicator box assuming that
- // it has specified indicator value.
-
- Rect r = mBounds;
- SInt32 startPt;
- SInt32 valuePt;
- SInt32 stopPt;
-
- this->GetIndicatorSpan(indicatorValue, &startPt, &valuePt, &stopPt);
-
- if (mIsHorizontal)
- {
- r.left = startPt;
- r.right = stopPt;
- }
- else
- {
- r.top = startPt;
- r.bottom = stopPt;
- }
-
- *indicatorBox = r;
- }
-
- SInt32 AGAScrollBar::GetIndicatorPixelRange(SInt32* proportionalIndicatorPixels)
- {
- // Return the pixel range that the center point of the indicator
- // can travel along the track, and also return the amount of
- // range reduction that is caused by proportional indicator growth.
- // Non-proportional indicators use the full track range, minus
- // the size of the indicator itself.
-
- SInt32 range;
-
- *proportionalIndicatorPixels = 0;
-
- if (mIsHorizontal)
- range = mBounds.right - mBounds.left - (2 * (kArrowSize + kIndicatorPixelInset)) + 1;
- else
- range = mBounds.bottom - mBounds.top - (2 * (kArrowSize + kIndicatorPixelInset)) + 1;
-
- if (mIsProportional)
- {
- SInt32 pagePixels;
-
- pagePixels =
- (range * (((float) mPageSize) / ((float) (mMaximum - mMinimum))));
-
- if (pagePixels > 0)
- {
- range -= pagePixels;
- *proportionalIndicatorPixels = pagePixels;
- }
- }
-
- return range;
- }
-
- void AGAScrollBar::GetIndicatorPixelEnds(SInt32* startPt, SInt32* stopPt)
- {
- // Return the start and end pixel locations of the indicator
- // track traveled by the center point of the indicator.
-
- SInt32 dontCare;
- SInt32 range = this->GetIndicatorPixelRange(&dontCare);
-
- if (mIsHorizontal)
- {
- *startPt = ((mBounds.left + mBounds.right) / 2) - (range / 2) - 1;
-
- // Bump by 1 for odd-number width.
- if (((mBounds.right - mBounds.left) & 1) != 0)
- (*startPt)++;
- }
- else
- {
- *startPt = ((mBounds.top + mBounds.bottom) / 2) - (range / 2) - 1;
-
- // Bump by 1 for odd-number height.
- if (((mBounds.bottom - mBounds.top) & 1) != 0)
- (*startPt)++;
- }
-
- *stopPt = *startPt + range; // avoid rounding of 1/2 pixel twice
- }
-
- void AGAScrollBar::GetIndicatorSpan(SInt32 value, SInt32* startPt, SInt32* valuePt, SInt32* stopPt)
- {
- // Return the pixel locations of the indicator's ends and value.
-
- SInt32 proportionalIndicatorPixels;
- SInt32 trackStart;
- SInt32 trackStop;
- SInt32 trackRange = this->GetIndicatorPixelRange(&proportionalIndicatorPixels);
-
- this->GetIndicatorPixelEnds(&trackStart, &trackStop);
-
- *valuePt = trackStart +
- (trackRange * (((float) (value - mMinimum)) / ((float) (mMaximum - mMinimum))));
-
- *startPt = *valuePt - kIndicatorPixelInset - (proportionalIndicatorPixels / 2);
- *stopPt = *startPt + (2 * kIndicatorPixelInset) + proportionalIndicatorPixels + 1;
- }
-
- //
- // AGASlider ---------------------------------------------------------------
- //
- // This class implements a standard AGA slider, with the additional
- // ability to perform live tracking and a proportional thumb.
- //
-
- // These regions are used momentarily while tracking the slider
- // indicator to clip and optimize redrawing.
- RgnHandle AGASlider::mgSavedIndicatorClip = ::NewRgn();
- RgnHandle AGASlider::mgOldIndicatorClip = ::NewRgn();
- RgnHandle AGASlider::mgNewIndicatorClip = ::NewRgn();
-
- AGASlider::AGASlider(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, const AGATextStyle& textStyle, SInt16 labelsID)
- : AGATrackingIndicator(bounds, minimum, maximum, initialValue)
- {
- // Construct with default options.
- mPageSize = 0;
-
- mLabelStringHandles = NULL;
- mJustification = teFlushDefault;
- mTextStyle = textStyle;
-
- if (labelsID == 0)
- {
- mSliderKind = kRectSlider;
-
- mLiveTracking = TestGrayCouncilDefault(kAGALiveRSliders);
- mIsProportional = TestGrayCouncilDefault(kAGAProportionalRSliders);
- }
- else
- {
- mSliderKind = kPointerSlider;
- this->SetLabelsFromResource(labelsID);
-
- mLiveTracking = TestGrayCouncilDefault(kAGALivePSliders);
- mIsProportional = TestGrayCouncilDefault(kAGAProportionalPSliders);
- }
- }
-
- AGASlider::AGASlider(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, const AGATextStyle& textStyle, SInt16 labelsID, SliderKind kind, Boolean liveTracking, Boolean proportional)
- : AGATrackingIndicator(bounds, minimum, maximum, initialValue, 1, liveTracking, proportional)
- {
- // Construct with specified options.
-
- mPageSize = 0;
-
- mLabelStringHandles = NULL;
- mJustification = teFlushDefault;
- mSliderKind = kind;
- mTextStyle = textStyle;
-
- this->SetLabelsFromResource(labelsID);
- }
-
- AGASlider::~AGASlider()
- {
- // Destruct by releasing memory allocated for labels.
-
- this->DisposeLabels();
- }
-
- void AGASlider::SetSliderKind(SliderKind kind)
- {
- // Set the slider kind (pointy or rectangular).
-
- mSliderKind = kind;
- }
-
- void AGASlider::SetLabelsFromResource(SInt16 stringListResourceID)
- {
- // Build the slider labels from the specified 'STR#' resource.
- // A label slot is allocated for each string in the resource;
- // there will be a visual label tick for each of these strings.
- // If the current min/max range is smaller than the number of
- // labels (i.e., it's uninitialized), the min/max range will
- // be set to match the number of labels.
-
- this->DisposeLabels();
-
- if (stringListResourceID != 0)
- {
- SInt16** stringListHandle = (SInt16**) ::GetResource('STR#', stringListResourceID);
- SInt16 numLabels = (stringListHandle == NULL) ? 0 : **stringListHandle;
-
- if (numLabels != 0)
- {
- mLabelStringHandles = ::NewHandleClear(numLabels * sizeof(StringHandle));
-
- for (SInt16 i = 0; i < numLabels; i++)
- {
- Str255 aLabel;
- StringHandle aStringHandle;
-
- ::GetIndString(aLabel, stringListResourceID, i+1);
- aStringHandle = ::NewString(aLabel);
-
- ((StringHandle*)(*mLabelStringHandles))[i] = aStringHandle;
- }
- }
-
- if ((mMaximum - mMinimum + 1) < numLabels)
- mMaximum = mMinimum + numLabels - 1;
- }
- }
-
- void AGASlider::SetNumLabels(UInt32 numLabels)
- {
- // Allocate slots for the specified number of labels.
- // Any existing labels are thrown away.
-
- this->DisposeLabels();
-
- mLabelStringHandles = ::NewHandleClear(numLabels * sizeof(StringHandle));
-
- if ((mMaximum - mMinimum + 1) < numLabels)
- mMaximum = mMinimum + numLabels - 1;
- }
-
- void AGASlider::SetLabel(UInt32 labelIndex, StringPtr itsLabel)
- {
- // Assign the specified string to the specified label slot.
-
- if (mLabelStringHandles != NULL)
- {
- UInt32 numLabels = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
-
- if (labelIndex < numLabels)
- ((StringHandle*)(*mLabelStringHandles))[labelIndex] = ::NewString(itsLabel);
- }
- }
-
- void AGASlider::GetLabel(UInt32 labelIndex, StringPtr itsLabel)
- {
- // Return the label string of the specified label slot.
-
- itsLabel[0] = 0;
-
- if (mLabelStringHandles != NULL)
- {
- UInt32 numLabels = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
-
- if (labelIndex < numLabels)
- {
- Ptr sourceStringPtr = (Ptr) *(((StringHandle*)(*mLabelStringHandles))[labelIndex]);
-
- ::BlockMoveData(sourceStringPtr, itsLabel, 1 + *sourceStringPtr);
- }
- }
- }
-
- void AGASlider::SetLabelsStyle(const AGATextStyle& textStyle)
- {
- // Set the QuickDraw text style for the labels.
-
- mTextStyle = textStyle;
- }
-
- void AGASlider::SetJustification(SInt32 justification)
- {
- // Set the justification of the slider. For vertical
- // sliders, default/left means the slider is on the
- // left and the labels are on the right; flush right
- // reverses this. For horizontal sliders, default/left
- // means the slider is above and the labels are below;
- // flush right reverses this.
- // In fact, for "teFlushDefault", the system script
- // direction is checked at runtime, so this is usually
- // what you should use. Use flush right or flush left
- // to force it one way or another.
-
- mJustification = justification;
- }
-
- SInt32 AGASlider::TrackTestPart(Point mouseLocation)
- {
- // Return the indicator part value if the mouse location
- // would hit the indicator.
-
- Rect indicatorRect;
-
- this->GetIndicatorBox(mValue, &indicatorRect);
-
- if (::PtInRect(mouseLocation, &indicatorRect))
- return kIndicatorPress;
- else
- return kNoTrackPress;
- }
-
- Boolean AGASlider::IsValidIndicatorTrackMouse(Point mouseLocation)
- {
- // Return true if the mouse location is reasonably close
- // to the indicator track. This will depend on the
- // justification.
-
- Rect okRect = mBounds;
-
- if (mIsHorizontal)
- {
- if (RuntimeJustify(mJustification) == teFlushLeft)
- okRect.bottom = okRect.top + kIndicatorWidth;
- else
- okRect.top = okRect.bottom - kIndicatorWidth;
- }
- else
- {
- if (RuntimeJustify(mJustification) == teFlushLeft)
- okRect.right = okRect.left + kIndicatorWidth;
- else
- okRect.left = okRect.right - kIndicatorWidth;
- }
-
- ::InsetRect(&okRect, -32, -32); // slop for mouse tracking
-
- return ::PtInRect(mouseLocation, &okRect);
- }
-
- SInt32 AGASlider::GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation)
- {
- // Return the new potential indicator value based on the mouse
- // delta from the original click location and the original value.
-
- SInt32 dontCare;
- SInt32 valueRange = mMaximum - mMinimum;
- SInt32 pixelRange = this->GetIndicatorPixelRange(&dontCare);
- SInt32 pixelDelta;
- float pixelFraction;
-
- if (mIsHorizontal)
- pixelDelta = newMouseLocation.h - originalMouseLocation.h;
- else
- pixelDelta = newMouseLocation.v - originalMouseLocation.v;
-
- pixelFraction = ((float) pixelDelta) / (float) pixelRange;
-
- float delta = pixelFraction * ((float) valueRange);
- delta += (float) 0.5; // round to nearest integer, don't just truncate fraction
-
- return originalValue + delta;
- }
-
- void AGASlider::DrawBackground()
- {
- CleansePen();
-
- // Paint the background and labels.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- ::RGBForeColor(&mBackgroundEraseColor);
- else
- ::RGBForeColor(&gAGARamp[rW]);
- }
-
- ::PaintRect(&mBounds);
-
- iter.Cleanup(); // Restore clipping since not yet destructed.
-
- this->DrawLabels();
-
- CleansePen();
- }
-
- void AGASlider::DrawIndicatorTrack()
- {
- CleansePen();
-
- // Draw the empty slider track.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- Rect trackFrame;
-
- this->GetTrackFrame(&trackFrame, kIncludeBackground);
-
- ::RGBForeColor(&mBackgroundEraseColor);
- ::PaintRect(&trackFrame);
-
- this->GetTrackFrame(&trackFrame, kTrackOnly);
-
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[rB]);
- else
- ::RGBForeColor(&gAGARamp[r8]);
-
- ::InsetRect(&trackFrame, 1, 1);
- ::FrameRect(&trackFrame);
-
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[r5]);
- else
- ::RGBForeColor(&gAGARamp[r4]);
-
- ::InsetRect(&trackFrame, 1, 1);
- ::PaintRect(&trackFrame);
- ::InsetRect(&trackFrame, -2, -2);
-
- ::MoveTo(trackFrame.left, trackFrame.bottom - 3);
- ::LineTo(trackFrame.left, trackFrame.top + 1);
- ::Line(1, 0);
- ::Line(0, -1);
- ::LineTo(trackFrame.right - 3, trackFrame.top);
-
- if (mIsHorizontal)
- {
- ::Move(1, 1);
- ::Line(0, 0);
- }
-
- ::RGBForeColor(&gAGARamp[rW]);
- ::MoveTo(trackFrame.left + 1, trackFrame.bottom - 2);
- ::Line(0, 0);
- ::Move(1, 1);
- ::LineTo(trackFrame.right - 2, trackFrame.bottom - 1);
- ::Line(0, -1);
- ::Line(1, 0);
- ::LineTo(trackFrame.right - 1, trackFrame.top + 2);
-
- if (! mIsHorizontal)
- {
- ::Move(-1, -1);
- ::Line(0, 0);
- }
- }
- else // 1 -bit
- {
- Rect trackFrame;
-
- this->GetTrackFrame(&trackFrame, kIncludeBackground);
-
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&trackFrame);
-
- this->GetTrackFrame(&trackFrame, kTrackOnly);
-
- ::RGBForeColor(&gAGARamp[rB]);
-
- if (! mEnabled)
- ::PenPat(&qd.gray);
-
- ::InsetRect(&trackFrame, 1, 1);
-
- ::MoveTo(trackFrame.left + 1, trackFrame.top);
- ::LineTo(trackFrame.right - 2, trackFrame.top);
- ::Move(1, 1);
- ::LineTo(trackFrame.right - 1, trackFrame.bottom - 2);
- ::Move(-1, 1);
- ::LineTo(trackFrame.left + 1, trackFrame.bottom - 1);
- ::Move(-1, -1);
- ::LineTo(trackFrame.left, trackFrame.top + 1);
-
- if (! mEnabled)
- ::PenPat(&qd.black);
- }
- }
-
- CleansePen();
- }
-
- void AGASlider::DrawIndicator()
- {
- CleansePen();
-
- // Draw the slider indicator.
-
- Rect indicatorRect;
-
- this->GetIndicatorBox(mValue, &indicatorRect);
-
- if (mSliderKind == kRectSlider)
- this->DrawRectIndicator(&indicatorRect, kNormalIndicator);
- else
- this->DrawPointerIndicator(&indicatorRect, kNormalIndicator);
-
- CleansePen();
- }
-
- void AGASlider::DrawGhost()
- {
- CleansePen();
-
- // Draw the ghost slider indicator.
-
- Rect indicatorRect;
-
- this->GetIndicatorBox(mGhostValue, &indicatorRect);
-
- if (mSliderKind == kRectSlider)
- this->DrawRectIndicator(&indicatorRect, kGhostIndicator);
- else
- this->DrawPointerIndicator(&indicatorRect, kGhostIndicator);
-
- CleansePen();
- }
-
- void AGASlider::DrawLabels()
- {
- CleansePen();
-
- // Draw the slider labels and ticks.
-
- UInt32 numHandles = 0;
-
- if (mLabelStringHandles != NULL)
- numHandles = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
-
- if (numHandles < 2) // Gotta at least label the ends, man!
- return;
-
- SInt16 tickRange;
- Point tickOrigin;
- Point drawDirection;
- Point moveDirection;
- Rect trackFrame;
- Boolean flushLeft = (RuntimeJustify(mJustification) == teFlushLeft);
- FontInfo fontInfo;
-
- mTextStyle.PrepareForDrawing();
- ::GetFontInfo(&fontInfo);
-
- this->GetTrackFrame(&trackFrame, kTrackOnly);
-
- if (mIsHorizontal)
- {
- tickRange = trackFrame.right - trackFrame.left - (2 * kLabelTickEndInset) - 1;
- drawDirection.h = 0;
- drawDirection.v = 1;
- moveDirection.h = 1;
- moveDirection.v = 0;
- tickOrigin.h = trackFrame.left + kLabelTickEndInset;
-
- if (flushLeft)
- tickOrigin.v = trackFrame.bottom + kLabelTickOffset;
- else
- tickOrigin.v = trackFrame.top - kLabelTickOffset - 2 - kLabelTickLength;
- }
- else
- {
- tickRange = trackFrame.bottom - trackFrame.top - (2 * kLabelTickEndInset) - 1;
- drawDirection.h = 1;
- drawDirection.v = 0;
- moveDirection.h = 0;
- moveDirection.v = 1;
- tickOrigin.v = trackFrame.top + kLabelTickEndInset;
-
- if (flushLeft)
- tickOrigin.h = trackFrame.right + kLabelTickOffset;
- else
- tickOrigin.h = trackFrame.left - kLabelTickOffset - 2 - kLabelTickLength;
- }
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- for (UInt32 i = 0; i < numHandles; i++)
- {
- Point tickLocation;
- float fraction = ((float) i) / ((float) (numHandles - 1));
-
- tickLocation.h = tickOrigin.h + (moveDirection.h * tickRange * fraction);
- tickLocation.v = tickOrigin.v + (moveDirection.v * tickRange * fraction);
-
- ::MoveTo(tickLocation.h, tickLocation.v);
-
- ::RGBForeColor(&gAGARamp[rB]);
-
- if (! mEnabled)
- {
- if (deep)
- ::RGBForeColor(&gAGARamp[r7]);
- else
- ::PenPat(&qd.gray);
- }
-
- ::Line(drawDirection.h * (kLabelTickLength + 1), drawDirection.v * (kLabelTickLength + 1));
-
- ::PenNormal();
-
- if (deep)
- {
- // If disabled, we still draw in order to erase the 7/W
- // shading pixels from prior enabled drawing.
-
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[r7]);
- else
- ::RGBForeColor(&mBackgroundEraseColor);
-
- ::Line(moveDirection.h, moveDirection.v);
- ::Line( - (kLabelTickLength * drawDirection.h), - (kLabelTickLength * drawDirection.v));
-
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[rW]);
-
- ::Move(-1, -1);
- ::Line(-moveDirection.h, -moveDirection.v);
- ::Line(drawDirection.h * kLabelTickLength, drawDirection.v * kLabelTickLength);
- }
-
- Str255 aLabel;
- Rect labelBox;
- SInt16 labelHeight = fontInfo.ascent + fontInfo.descent;
- SInt16 labelWidth;
- SInt32 textJustification;
-
- this->GetLabel(i, aLabel);
- labelWidth = ::StringWidth(aLabel);
-
- if (mIsHorizontal)
- {
- textJustification = teCenter;
- labelBox.left = tickLocation.h - (labelWidth / 2);
- labelBox.right = labelBox.left + labelWidth;
-
- if (flushLeft)
- {
- labelBox.top = tickLocation.v + 9;
- labelBox.bottom = labelBox.top + labelHeight;
- }
- else
- {
- labelBox.bottom = tickLocation.v - 2;
- labelBox.top = labelBox.bottom - labelHeight;
- }
- }
- else
- {
- textJustification = mJustification;
- labelBox.top = tickLocation.v - (labelHeight / 2);
- labelBox.bottom = labelBox.top + labelHeight;
-
- if (flushLeft)
- {
- labelBox.left = tickLocation.h + 11;
- labelBox.right = labelBox.left + labelWidth;
- }
- else
- {
- labelBox.right = tickLocation.h - 2;
- labelBox.left = labelBox.right - labelWidth;
- }
- }
-
- //
- // To make view layout simpler, we assume that the labels may
- // extend outside the mBounds. So if this happens
- // we need to make sure we aren't being clipped out, but also
- // make sure we don't extend the unclipped area out to other
- // screens during device iteration.
- //
-
- RgnHandle savedRegion = NULL;
-
- if ((labelBox.left < mBounds.left) ||
- (labelBox.right > mBounds.right))
- {
- savedRegion = ::NewRgn();
- ::GetClip(savedRegion);
- ::InsetRect(&labelBox, -1, -1);
- ::ClipRect(&labelBox);
- ::InsetRect(&labelBox, 1, 1);
-
- iter.ClipFurtherToCurrentDevice();
- }
-
- AGAStringOut(aLabel, &labelBox, kNoTruncation, textJustification, mEnabled ? kNormalOutput : kDisabledOutput, deep, mTextStyle);
-
- if (savedRegion != NULL)
- {
- ::SetClip(savedRegion);
- ::DisposeRgn(savedRegion);
- }
- }
- }
-
- CleansePen();
- }
-
- void AGASlider::DrawRectIndicator(Rect* indicatorRect, Boolean isGhost)
- {
- CleansePen();
-
- // Draw the rectangular slider indicator at the
- // specified location. The location will be sized
- // to account for a proportional indicator.
-
- enum { Frame, Fill, Corner, Light, TL, BR, Dark, Grip, BG, kNumIndicatorColors };
-
- UInt8 colorIndexes[kNumIndicatorColors];
- Rect r = *indicatorRect;
- Point drawDirection;
- Point moveDirection;
- SInt16 lineLength;
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- colorIndexes[BG] = r2;
-
- if (isGhost)
- {
- colorIndexes[Frame] = r7;
- colorIndexes[Fill] = r2;
- colorIndexes[Corner] = r1;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = r4;
- colorIndexes[Dark] = r5;
- colorIndexes[Grip] = rW;
- }
- else if (! mEnabled)
- {
- colorIndexes[Frame] = r8;
- colorIndexes[Fill] = r2;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = r1;
- colorIndexes[BR] = r4;
- // n/a colorIndexes[Dark] = r9;
- colorIndexes[Grip] = r1;
- }
- else if (mIsPressed)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = r8;
- colorIndexes[Corner] = r3;
- colorIndexes[Light] = r3;
- colorIndexes[TL] = r5;
- colorIndexes[BR] = r10;
- colorIndexes[Dark] = r12;
- colorIndexes[Grip] = r5;
- }
- else // normal
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = r5;
- colorIndexes[Corner] = r1;
- colorIndexes[Light] = r1;
- colorIndexes[TL] = r3;
- colorIndexes[BR] = r8;
- colorIndexes[Dark] = r10;
- colorIndexes[Grip] = r3;
- }
- }
- else // 1-bit
- {
- colorIndexes[BG] = rW;
-
- if (isGhost)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rW;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = rW;
- colorIndexes[Dark] = rW;
- colorIndexes[Grip] = rB;
- }
- else if (! mEnabled)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rW;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = rW;
- colorIndexes[Dark] = rW;
- colorIndexes[Grip] = rW;
- }
- else if (mIsPressed)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rB;
- colorIndexes[Corner] = rB;
- colorIndexes[Light] = rB;
- colorIndexes[TL] = rB;
- colorIndexes[BR] = rB;
- colorIndexes[Dark] = rB;
- colorIndexes[Grip] = rW;
- }
- else // normal
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rW;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = rW;
- colorIndexes[Dark] = rW;
- colorIndexes[Grip] = rB;
- }
- }
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Frame]]);
- ::FrameRect(&r);
- ::RGBForeColor(&gAGARamp[colorIndexes[BG]]);
- ::MoveTo(r.left, r.top);
- ::Line(0, 0);
- ::MoveTo(r.right - 1, r.top);
- ::Line(0, 0);
- ::MoveTo(r.right - 1, r.bottom - 1);
- ::Line(0, 0);
- ::MoveTo(r.left, r.bottom - 1);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
- ::InsetRect(&r, 1, 1);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
- ::MoveTo(r.left + 1, r.top + 1);
- ::Line(0, 0);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 2);
- ::Move(1, -1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::Move(1, 1);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.left + 2, r.bottom - 2);
-
- if (mIsHorizontal)
- {
- ::SetPt(&drawDirection, 0, 1);
- ::SetPt(&moveDirection, 1, 0);
- lineLength = r.bottom - r.top - 10;
- }
- else
- {
- ::SetPt(&drawDirection, 1, 0);
- ::SetPt(&moveDirection, 0, 1);
- lineLength = r.right - r.left - 10;
- }
-
- if (mEnabled)
- {
- ::MoveTo(r.left + 3 + drawDirection.h + (moveDirection.h * (((r.right - r.left) / 2) - 6)),
- r.top + 3 + drawDirection.v + (moveDirection.v * (((r.bottom - r.top) / 2) - 6)));
-
- if (! deep)
- ::Move(moveDirection.h, moveDirection.v);
-
- for (SInt32 i = 0; i < 3; i++)
- {
- ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
- ::Line(drawDirection.h, drawDirection.v);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Grip]]);
- ::Line(drawDirection.h * (lineLength-1), drawDirection.v * (lineLength-1));
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(drawDirection.h, drawDirection.v);
- ::RGBForeColor(&gAGARamp[colorIndexes[Dark]]);
- ::Line(- (drawDirection.h * lineLength), - (drawDirection.v * lineLength));
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(- drawDirection.h, - drawDirection.v);
- }
- }
-
- if (isGhost && deep)
- {
- // Draw the little see-thru track slides.
- // They run inverse draw direction from the grip lines.
- // To handle proportional indicators, we need to vary
- // the length of the track slides on the flat part.
- SInt32 wholeFlatLength;
- SInt32 firstFlatLength;
- SInt32 remainingFlatLength;
-
- if (mIsHorizontal)
- wholeFlatLength = r.right - r.left - 10;
- else
- wholeFlatLength = r.bottom - r.top - 10;
-
- firstFlatLength = wholeFlatLength / 2;
- remainingFlatLength = wholeFlatLength - firstFlatLength; // don't round down twice
-
- ::RGBForeColor(&gAGARamp[r11]);
- ::MoveTo(r.left + (drawDirection.h * 5), r.top + (drawDirection.v * 5));
-
- for (UInt32 i = 0; i < 2; i++)
- {
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(moveDirection.h * firstFlatLength, moveDirection.v * firstFlatLength);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r9]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r9]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r9]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(moveDirection.h * remainingFlatLength, moveDirection.v * remainingFlatLength);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r11]);
- ::Line(0, 0);
-
- ::MoveTo(r.left + (drawDirection.h * 9), r.top + (drawDirection.v * 9));
- }
- }
- }
-
- CleansePen();
- }
-
- void AGASlider::DrawPointerIndicator(Rect* indicatorRect, Boolean isGhost)
- {
- CleansePen();
-
- // Draw the pointy slider indicator at the
- // specified location. The location will be sized
- // to account for a proportional indicator.
-
- enum { Frame, Fill, Corner, Light, TL, Grip, BR, Dark, kNumIndicatorColors };
-
- UInt8 colorIndexes[kNumIndicatorColors];
- Rect r = *indicatorRect;
- Point drawDirection;
- Point moveDirection;
- SInt16 lineLength;
- SInt16 propExtra; // extra pixels due to proportional indicator shape
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- if (isGhost)
- {
- colorIndexes[Frame] = r7;
- colorIndexes[Fill] = r2;
- colorIndexes[Corner] = r1;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[Grip] = rW;
- colorIndexes[BR] = r4;
- colorIndexes[Dark] = r5;
- }
- else if (! mEnabled)
- {
- colorIndexes[Frame] = r8;
- colorIndexes[Fill] = r2;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = r1;
- colorIndexes[Grip] = r1;
- colorIndexes[BR] = r4;
- // n/a colorIndexes[Dark] = r9;
- }
- else if (mIsPressed)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = r8;
- colorIndexes[Corner] = r3;
- colorIndexes[Light] = r3;
- colorIndexes[TL] = r5;
- colorIndexes[Grip] = r5;
- colorIndexes[BR] = r10;
- colorIndexes[Dark] = r12;
- }
- else // normal
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = r5;
- colorIndexes[Corner] = r1;
- colorIndexes[Light] = r1;
- colorIndexes[TL] = r3;
- colorIndexes[Grip] = r3;
- colorIndexes[BR] = r8;
- colorIndexes[Dark] = r10;
- }
- }
- else // 1-bit
- {
- if (isGhost)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rW;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[Grip] = rW;
- colorIndexes[BR] = rW;
- colorIndexes[Dark] = rW;
- }
- else if (! mEnabled)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rW;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[Grip] = rW;
- colorIndexes[BR] = rW;
- colorIndexes[Dark] = rW;
- }
- else if (mIsPressed)
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rB;
- colorIndexes[Corner] = rB;
- colorIndexes[Light] = rB;
- colorIndexes[TL] = rB;
- colorIndexes[Grip] = rW;
- colorIndexes[BR] = rB;
- colorIndexes[Dark] = rB;
- }
- else // normal
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = rW;
- colorIndexes[Corner] = rW;
- colorIndexes[Light] = rW;
- colorIndexes[TL] = rW;
- colorIndexes[Grip] = rB;
- colorIndexes[BR] = rW;
- colorIndexes[Dark] = rW;
- }
- }
-
- if (mIsHorizontal)
- {
- ::SetPt(&drawDirection, 0, 1);
- ::SetPt(&moveDirection, 1, 0);
- lineLength = r.bottom - r.top - 11;
- propExtra = MaxSInt16(0, r.right - r.left - 15);
- }
- else
- {
- ::SetPt(&drawDirection, 1, 0);
- ::SetPt(&moveDirection, 0, 1);
- lineLength = r.right - r.left - 11;
- propExtra = MaxSInt16(0, r.bottom - r.top - 15);
- }
-
- PolyHandle pointerPoly = ::OpenPoly();
-
- this->BuildPointerIndicator(indicatorRect);
-
- ::ClosePoly();
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
- ::PaintPoly(pointerPoly);
- ::RGBForeColor(&gAGARamp[colorIndexes[Frame]]);
- ::FramePoly(pointerPoly);
-
- ::KillPoly(pointerPoly);
-
- if (mIsHorizontal)
- {
- if (RuntimeJustify(mJustification) == teFlushLeft)
- {
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
- ::Line(0, 0);
- ::MoveTo(r.right - 2, r.top + 2);
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::LineTo(r.right - 2, r.top + 9);
- ::Line(-5, 5);
- ::Line(-2 - propExtra, 0);
- ::Line(-5, -5);
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::LineTo(r.left + 1, r.top + 2);
- ::Line(1, -1);
- ::LineTo(r.right - 3, r.top + 1);
- }
- else
- {
- ::MoveTo(r.right - 6, r.top + 2);
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::Line(4, 4);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.left + 2, r.bottom - 2);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::Line(0, -7);
- ::Line(5, -5);
- ::Line(1 + propExtra, 0);
- ::MoveTo(r.left + 6, r.top + 1);
- ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
- ::Line(0, 0);
- ::Move(-5, 5);
- ::Line(0, 0);
- }
- }
- else
- {
- if (RuntimeJustify(mJustification) == teFlushLeft)
- {
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
- ::Line(0, 0);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::LineTo(r.left + 1, r.top + 2);
- ::Line(1, -1);
- ::Line(7, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::Line(4, 4);
- ::Line(0, 2 + propExtra);
- ::Line(-5, 5);
- ::Line(-7, 0);
- }
- else
- {
- ::MoveTo(r.left + 2, r.top + 9 + propExtra);
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::Line(4, 4);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.top + 2);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::Line(-7, 0);
- ::Line(-5, 5);
- ::Line(0, 1 + propExtra);
- ::Move(0, - (1 + propExtra));
- ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
- ::Line(0, 0);
- ::Move(5, -5);
- ::Line(0, 0);
- }
- }
-
- if (mEnabled)
- {
- ::MoveTo(r.left + 3 + (moveDirection.h * (((r.right - r.left) / 2) - 6)),
- r.top + 3 + (moveDirection.v * (((r.bottom - r.top) / 2) - 6)));
-
- if (RuntimeJustify(mJustification) == teFlushRight)
- ::Move(2 * drawDirection.h, 2 * drawDirection.v);
-
- if (! deep)
- ::Move(moveDirection.h, moveDirection.v);
-
- for (SInt32 i = 0; i < 3; i++)
- {
- ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
- ::Line(drawDirection.h, drawDirection.v);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Grip]]);
- ::Line(drawDirection.h * (lineLength-1), drawDirection.v * (lineLength-1));
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(drawDirection.h, drawDirection.v);
- ::RGBForeColor(&gAGARamp[colorIndexes[Dark]]);
- ::Line(- (drawDirection.h * lineLength), - (drawDirection.v * lineLength));
-
- ::Move(moveDirection.h, moveDirection.v);
- ::Move(- drawDirection.h, - drawDirection.v);
- }
- }
-
- if (isGhost && deep)
- {
- // Draw the little see-thru track slides.
- // They run inverse draw direction from the grip lines.
- // To handle proportional indicators, we need to vary
- // the length of the track slides on the flat part.
- SInt32 wholeFlatLength;
- SInt32 firstFlatLength;
- SInt32 remainingFlatLength;
-
- if (mIsHorizontal)
- wholeFlatLength = r.right - r.left - 10;
- else
- wholeFlatLength = r.bottom - r.top - 10;
-
- firstFlatLength = wholeFlatLength / 2;
- remainingFlatLength = wholeFlatLength - firstFlatLength; // don't round down twice
-
- ::RGBForeColor(&gAGARamp[r11]);
- ::MoveTo(r.left + (drawDirection.h * 4), r.top + (drawDirection.v * 4));
-
- for (UInt32 i = 0; i < 2; i++)
- {
- if (RuntimeJustify(mJustification) == teFlushRight)
- ::Move(3 * drawDirection.h, 3 * drawDirection.v);
-
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(moveDirection.h * firstFlatLength, moveDirection.v * firstFlatLength);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r9]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r9]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r2]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r9]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(moveDirection.h * remainingFlatLength, moveDirection.v * remainingFlatLength);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(moveDirection.h, moveDirection.v);
- ::RGBForeColor(&gAGARamp[r11]);
- ::Line(0, 0);
-
- ::MoveTo(r.left + (drawDirection.h * 8), r.top + (drawDirection.v * 8));
- }
- }
- }
-
- CleansePen();
- }
-
- void AGASlider::BuildPointerIndicator(Rect* indicatorRect)
- {
- // Perform the QuickDraw framing commands to build the
- // pointy indicator. This function is called while wrapped
- // in polygon or region building calls. The caller will
- // use the resulting polygon or region to frame, fill,
- // or clip.
-
- Rect r = *indicatorRect;
- SInt16 propExtra;
-
- if (mIsHorizontal)
- {
- propExtra = MaxSInt16(0, r.right - r.left - 15);
-
- if (RuntimeJustify(mJustification) == teFlushLeft)
- {
- ::MoveTo(r.right - 1, r.top + 1);
- ::LineTo(r.right - 1, r.bottom - 7);
- ::Line(-6, 6);
- ::Line(-2 - propExtra, 0);
- ::Line(-6, -6);
- ::LineTo(r.left, r.top + 1);
- ::Line(1, -1);
- ::LineTo(r.right - 2, r.top);
- ::Line(1, 1);
- }
- else
- {
- ::MoveTo(r.left, r.bottom - 2);
- ::LineTo(r.left, r.top + 6);
- ::Line(6, -6);
- ::Line(2 + propExtra, 0);
- ::Line(6, 6);
- ::LineTo(r.right - 1, r.bottom - 2);
- ::Line(-1, 1);
- ::LineTo(r.left + 1, r.bottom - 1);
- ::Line(-1, -1);
- }
- }
- else
- {
- propExtra = MaxSInt16(0, r.bottom - r.top - 15);
-
- if (RuntimeJustify(mJustification) == teFlushLeft)
- {
- ::MoveTo(r.left + 1, r.top);
- ::LineTo(r.right - 7, r.top);
- ::Line(6, 6);
- ::Line(0, 2 + propExtra);
- ::Line(-6, 6);
- ::LineTo(r.left + 1, r.bottom - 1);
- ::Line(-1, -1);
- ::LineTo(r.left, r.top + 1);
- ::Line(1, -1);
- }
- else
- {
- ::MoveTo(r.right - 2, r.bottom - 1);
- ::LineTo(r.left + 6, r.bottom - 1);
- ::Line(-6, -6);
- ::Line(0, -2 - propExtra);
- ::Line(6, -6);
- ::LineTo(r.right - 2, r.top);
- ::Line(1, 1);
- ::LineTo(r.right - 1, r.bottom - 2);
- ::Line(-1, 1);
- }
- }
- }
-
- void AGASlider::RemoveIndicator(SInt32 newValue)
- {
- // Draw the background to remove the indicator
- // at the specified value.
-
- //
- // Set clipping so we only draw the track to
- // wipe out the old indicator, but not where
- // the new indicator will get drawn anyway.
- // This reduces flicker. Polygon geometry makes
- // tweaking necessary and still imperfect.
- //
-
- ::GetClip(mgSavedIndicatorClip);
-
- if (newValue != mValue)
- {
- Rect oldIndicatorBox;
- Rect newIndicatorBox;
-
- this->GetIndicatorBox(mValue, &oldIndicatorBox);
- this->GetIndicatorBox(newValue, &newIndicatorBox);
-
- if (mSliderKind == kRectSlider)
- {
- ::RectRgn(mgOldIndicatorClip, &oldIndicatorBox);
- ::RectRgn(mgNewIndicatorClip, &newIndicatorBox);
- }
- else
- {
- //
- // For optimal clipping, because of polygon and
- // region geometry, we have to tweak the regions
- // a little bit.
- //
-
- RgnHandle tempRegion = ::NewRgn();
-
- ::OpenRgn();
- this->BuildPointerIndicator(&oldIndicatorBox);
- ::CloseRgn(mgOldIndicatorClip);
- ::CopyRgn(mgOldIndicatorClip, tempRegion);
- ::OffsetRgn(tempRegion, 1, 1);
- ::InsetRgn(tempRegion, -1, -1);
- ::UnionRgn(mgOldIndicatorClip, tempRegion, mgOldIndicatorClip);
-
- ::OpenRgn();
- this->BuildPointerIndicator(&newIndicatorBox);
- ::CloseRgn(mgNewIndicatorClip);
- ::CopyRgn(mgNewIndicatorClip, tempRegion);
- ::UnionRgn(mgNewIndicatorClip, tempRegion, mgNewIndicatorClip);
-
- ::DisposeRgn(tempRegion);
- }
-
- ::DiffRgn(mgOldIndicatorClip, mgNewIndicatorClip, mgOldIndicatorClip);
-
- ::SetClip(mgOldIndicatorClip);
- }
-
- this->DrawIndicatorTrack();
-
- ::SetClip(mgSavedIndicatorClip);
- }
-
- void AGASlider::RemoveGhost(SInt32 newValue)
- {
- // Draw the background necessary to remove the
- // ghost indicator while not removing the solid
- // value indicator.
-
- Rect r;
- RgnHandle savedClip = ::NewRgn();
-
- ::GetClip(savedClip);
-
- this->GetIndicatorBox(mGhostValue, &r);
- ::ClipRect(&r);
- this->DrawIndicatorTrack();
- this->DrawIndicator();
-
- ::SetClip(savedClip);
- ::DisposeRgn(savedClip);
- }
-
- void AGASlider::GetTrackFrame(Rect* trackFrame, Boolean includeBackground)
- {
- // Return the rectangle that bounds just the indicator
- // track, including shading pixels but not the area covered
- // by the indicator itself.
-
- Boolean leftJustify = (RuntimeJustify(mJustification) == teFlushLeft);
-
- *trackFrame = mBounds;
-
- if (mIsHorizontal)
- {
- if (leftJustify)
- {
- trackFrame->top += 4;
- trackFrame->bottom = trackFrame->top + 7;
- }
- else
- {
- trackFrame->bottom -= 4;
- trackFrame->top = trackFrame->bottom - 7;
- }
-
- if (includeBackground)
- {
- trackFrame->top -= leftJustify ? 4 : 6;
- trackFrame->bottom += leftJustify ? 6 : 4;
- }
- }
- else
- {
- if (leftJustify)
- {
- trackFrame->left += 4;
- trackFrame->right = trackFrame->left + 7;
- }
- else
- {
- trackFrame->right -= 4;
- trackFrame->left = trackFrame->right - 7;
- }
-
- if (includeBackground)
- {
- trackFrame->left -= leftJustify ? 4 : 6;
- trackFrame->right += leftJustify ? 6 : 4;
- }
- }
- }
-
- void AGASlider::GetIndicatorBox(SInt32 indicatorValue, Rect* indicatorBox)
- {
- // Return the box that defines the indicator's location
- // given the specified indicator value.
-
- Rect r = mBounds;
- SInt32 startPt;
- SInt32 valuePt;
- SInt32 stopPt;
-
- this->GetIndicatorSpan(indicatorValue, &startPt, &valuePt, &stopPt);
-
- if (mIsHorizontal)
- {
- r.left = startPt;
- r.right = stopPt;
-
- if (RuntimeJustify(mJustification) == teFlushLeft)
- {
- if (mSliderKind == kPointerSlider)
- r.top++;
-
- r.bottom = r.top + kIndicatorWidth;
- }
- else
- {
- if (mSliderKind == kPointerSlider)
- r.bottom--;
-
- r.top = r.bottom - kIndicatorWidth;
- }
- }
- else
- {
- r.top = startPt;
- r.bottom = stopPt;
-
- if (RuntimeJustify(mJustification) == teFlushLeft)
- {
- if (mSliderKind == kPointerSlider)
- r.left++;
-
- r.right = r.left + kIndicatorWidth;
- }
- else
- {
- if (mSliderKind == kPointerSlider)
- r.right--;
-
- r.left = r.right - kIndicatorWidth;
- }
- }
-
- *indicatorBox = r;
- }
-
- SInt32 AGASlider::GetIndicatorPixelRange(SInt32* proportionalIndicatorPixels)
- {
- // Return the pixel range that the center point of the indicator
- // can travel along the track, and also return the amount of
- // range reduction that is caused by proportional indicator growth.
- // Non-proportional indicators use the full track range, minus
- // the size of the indicator itself.
-
- SInt32 range;
- SInt32 indicatorInset = (mSliderKind == kRectSlider) ? kRectIndicatorPixelInset : kPointerIndicatorPixelInset;
-
- *proportionalIndicatorPixels = 0;
-
- if (mIsHorizontal)
- range = mBounds.right - mBounds.left - (2 * (kEndGapSize + indicatorInset)) + 1;
- else
- range = mBounds.bottom - mBounds.top - (2 * (kEndGapSize + indicatorInset)) + 1;
-
- if (mIsProportional)
- {
- SInt32 pagePixels;
-
- pagePixels =
- (range * (((float) mPageSize) / ((float) (mMaximum - mMinimum))));
-
- if (pagePixels > 0)
- {
- range -= pagePixels;
- *proportionalIndicatorPixels = pagePixels;
- }
- }
-
- return range;
- }
-
- void AGASlider::GetIndicatorPixelEnds(SInt32* startPt, SInt32* stopPt)
- {
- // Return the start and end pixel locations of the indicator
- // track traveled by the center point of the indicator.
-
- SInt32 dontCare;
- SInt32 range = this->GetIndicatorPixelRange(&dontCare);
-
- if (mIsHorizontal)
- *startPt = ((mBounds.left + mBounds.right) / 2) - (range / 2) - 1;
- else
- *startPt = ((mBounds.top + mBounds.bottom) / 2) - (range / 2) - 1;
-
- *stopPt = *startPt + range; // avoid rounding of 1/2 pixel twice
- }
-
- void AGASlider::GetIndicatorSpan(SInt32 value, SInt32* startPt, SInt32* valuePt, SInt32* stopPt)
- {
- // Return the pixel locations of the indicator's ends and value.
-
- SInt32 proportionalIndicatorPixels;
- SInt32 trackStart;
- SInt32 trackStop;
- SInt32 trackRange = this->GetIndicatorPixelRange(&proportionalIndicatorPixels);
- SInt32 indicatorInset = (mSliderKind == kRectSlider) ? kRectIndicatorPixelInset : kPointerIndicatorPixelInset;
-
- this->GetIndicatorPixelEnds(&trackStart, &trackStop);
-
- *valuePt = trackStart +
- (trackRange * (((float) (value - mMinimum)) / ((float) (mMaximum - mMinimum))));
-
- *startPt = *valuePt - indicatorInset - (proportionalIndicatorPixels / 2);
- *stopPt = *startPt + (2 * indicatorInset) + proportionalIndicatorPixels + 1;
- }
-
- void AGASlider::DisposeLabels()
- {
- // Release the memory allocated for slider labels.
-
- if (mLabelStringHandles != NULL)
- {
- UInt32 numHandles = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
-
- for (UInt32 i = 0; i < numHandles; i++)
- ::DisposeHandle((Handle) ((StringHandle*)(*mLabelStringHandles))[i]);
-
- ::DisposeHandle(mLabelStringHandles);
- }
- }
-
- //
- // AGAPopupMenu ---------------------------------------------------------------
- //
- // This class implements a standard popup menu look, and handles the
- // mouse by calling PopUpMenuSelect such that the visible menu is
- // located where the AGA says it should.
- //
-
- AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& textStyle, WidthAdjust adjustment)
- : AGAObject(bounds)
- {
- // Construct without a menu installed.
-
- mMenuID = 0;
- mMenuRef = NULL;
- mMenuRefDisposalKind = kDontDispose;
- mCurrentItemNo = 1;
- mWidthAdjust = adjustment;
- mTextStyle = textStyle;
- PLstrcpy(mTitle, title);
- mTitleOffset = titleOffset;
- mTitleJustification = titleJustification;
- }
-
- AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& textStyle, WidthAdjust adjustment, MenuRef itsMenuRef, DisposalKind menuRefDisposalKind)
- : AGAObject(bounds)
- {
- // Construct with specified MenuRef.
-
- if (itsMenuRef == NULL)
- mMenuID = 0;
- else
- mMenuID = (**itsMenuRef).menuID;
-
- mMenuRef = itsMenuRef;
- mMenuRefDisposalKind = menuRefDisposalKind;
-
- mCurrentItemNo = 1;
- mWidthAdjust = adjustment;
- mTextStyle = textStyle;
- PLstrcpy(mTitle, title);
- mTitleOffset = titleOffset;
- mTitleJustification = titleJustification;
- }
-
- AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& textStyle, WidthAdjust adjustment, SInt16 itemsStringListID, SInt16 newMenuID)
- : AGAObject(bounds)
- {
- // Construct with menu built from strings in a 'STR#' resource.
-
- mMenuID = newMenuID;
- mMenuRef = ::NewMenu(newMenuID, "\pAGA");
- mMenuRefDisposalKind = kDispose;
- mCurrentItemNo = 1;
- mWidthAdjust = adjustment;
- mTextStyle = textStyle;
- PLstrcpy(mTitle, title);
- mTitleOffset = titleOffset;
- mTitleJustification = titleJustification;
-
- Handle stringListHandle = ::GetResource('STR#', itemsStringListID);
- if (stringListHandle != NULL)
- {
- SInt16 numStrings = **((SInt16 **) stringListHandle);
-
- for (SInt16 stringIndex = 1; stringIndex <= numStrings; stringIndex++)
- {
- Str255 aString;
-
- ::GetIndString(aString, itemsStringListID, stringIndex);
-
- // Use SetMenuItemText to avoid metacharacter interpretation.
- ::AppendMenu(mMenuRef, "\pXXX");
- ::SetMenuItemText(mMenuRef, stringIndex, aString);
- }
- }
- }
-
- AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& textStyle, WidthAdjust adjustment, ResType appendResourceType, SInt16 newMenuID)
- : AGAObject(bounds)
- {
- // Construct with menu built from specified appended resource type.
- // Typical use is for a Fonts menu, using resource type 'FOND'.
-
- mMenuID = newMenuID;
- mMenuRef = ::NewMenu(newMenuID, "\pAGA");
- mMenuRefDisposalKind = kDispose;
- mCurrentItemNo = 1;
- mWidthAdjust = adjustment;
- mTextStyle = textStyle;
- PLstrcpy(mTitle, title);
- mTitleOffset = titleOffset;
- mTitleJustification = titleJustification;
-
- ::AppendResMenu(mMenuRef, appendResourceType);
- }
-
- AGAPopupMenu::~AGAPopupMenu()
- {
- // Destruct by cleaning up the menu data.
- // This depends on how the menu was created.
-
- this->DisposeExistingMenuRef();
- }
-
- void AGAPopupMenu::DisposeExistingMenuRef()
- {
- // Clean up the menu data based on how it was created
- // or how the client code specified.
-
- if (mMenuRef != NULL)
- {
- if (mMenuRefDisposalKind == kDispose)
- ::DisposeMenu(mMenuRef);
- else if (mMenuRefDisposalKind == kRelease)
- ::ReleaseResource((Handle) mMenuRef);
- }
-
- mMenuRefDisposalKind = kDontDispose;
- }
-
- void AGAPopupMenu::SetMenuRef(MenuRef itsMenuRef, DisposalKind menuRefDisposalKind)
- {
- // Install the specified MenuRef.
-
- this->DisposeExistingMenuRef();
-
- if (itsMenuRef == NULL)
- mMenuID = 0;
- else
- mMenuID = (**itsMenuRef).menuID;
-
- mMenuRef = itsMenuRef;
- mMenuRefDisposalKind = menuRefDisposalKind;
-
- mCurrentItemNo = 1;
- }
-
- void AGAPopupMenu::SetWidthAdjustment(WidthAdjust adjustment)
- {
- // Set the width adjustment, which determines how wide
- // the closed menu appears.
-
- mWidthAdjust = adjustment;
- }
-
- void AGAPopupMenu::DrawObject()
- {
- // Draw the unpressed popup menu "button".
-
- this->DrawButton(kNotPressed);
- }
-
- Boolean AGAPopupMenu::TrackMouse(Point mouseLocation)
- {
- // Track the mouse in the popup, and return true
- // if it caused the current popup selection to change.
-
- Boolean selectionChanged;
- SInt32 menuResult;
- Point globalOrigin;
-
- this->DrawButton(kPressed);
-
- ::SetPt(&globalOrigin, mBounds.left + mTitleOffset, mBounds.bottom);
- ::LocalToGlobal(&globalOrigin);
-
- ::InsertMenu(mMenuRef, -1); // put it in the hierarchical list
-
- ::CheckItem(mMenuRef, mCurrentItemNo, TRUE);
- menuResult = ::PopUpMenuSelect(mMenuRef, globalOrigin.v, globalOrigin.h + 1, 1);
- ::CheckItem(mMenuRef, mCurrentItemNo, FALSE);
-
- ::DeleteMenu((**mMenuRef).menuID); // get it out of the hierarchical list
-
- selectionChanged = (menuResult != 0);
-
- if (selectionChanged)
- this->SetCurrentItemNo(menuResult & 0x0000FFFF, kDontRedraw);
-
- this->DrawButton(kNotPressed);
-
- return selectionChanged;
- }
-
- SInt16 AGAPopupMenu::GetCurrentItemNo()
- {
- // Return the currently selected item index (1-based).
-
- return mCurrentItemNo;
- }
-
- void AGAPopupMenu::SetCurrentItemNo(SInt16 newItemNo, Boolean redraw)
- {
- // Set the current item index (1-based), optionally redraw.
-
- mCurrentItemNo = newItemNo;
-
- if (redraw)
- this->DrawButton(kNotPressed);
- }
-
- void AGAPopupMenu::GetCurrentItemText(StringPtr itemText)
- {
- // Return the menu item text of the currently selected item.
-
- itemText[0] = 0;
-
- if (mMenuRef != NULL)
- ::GetMenuItemText(mMenuRef, this->GetCurrentItemNo(), itemText);
- }
-
- Boolean AGAPopupMenu::SetCurrentItemText(StringPtr itemTextToMatch, Boolean redraw)
- {
- // Set the current item index to the item whose text
- // matches the specified string. Optionally redraw.
-
- Boolean wasMatchFound = FALSE;
- SInt16 numItems = 0;
-
- if (mMenuRef != NULL)
- numItems = ::CountMenuItems(mMenuRef);
-
- for (SInt16 itemIndex = 1; itemIndex <= numItems; itemIndex++)
- {
- Str255 itemText;
-
- ::GetMenuItemText(mMenuRef, itemIndex, itemText);
-
- if (::EqualString(itemText, itemTextToMatch, TRUE, TRUE))
- {
- wasMatchFound = TRUE;
- this->SetCurrentItemNo(itemIndex, redraw);
- break;
- }
- }
-
- return wasMatchFound;
- }
-
- void AGAPopupMenu::DrawButton(Boolean pressed)
- {
- // Draw the popup button in the specified state.
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (! mEnabled)
- this->DrawButtonDisabled(deep);
- else if (pressed)
- this->DrawButtonPressed(deep);
- else
- this->DrawButtonNormal(deep);
- }
- }
-
- void AGAPopupMenu::DrawButtonNormal(Boolean deep)
- {
- CleansePen();
-
- // Draw the popup button in enabled/unpressed state.
-
- Rect r;
- Str255 currentItemText;
-
- this->GetCurrentItemText(currentItemText);
- this->GetButtonBounds(&r);
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(r.right - r.left - 6, 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, r.bottom - r.top - 6);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(- (r.right - r.left - 6), 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, -(r.bottom - r.top - 6));
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
-
- if (r.right - r.left > kPopupArrowSectionWidth)
- {
- // Add flat section inner pixels.
- ::RGBForeColor(&gAGARamp[rW]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 2);
- ::Move(1, -1);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 1);
- ::RGBForeColor(&gAGARamp[r1]);
- ::Line(0, 0);
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.bottom - 2);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 2);
-
- // Add arrow section left corners
- ::RGBForeColor(&gAGARamp[r4]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.bottom - 2);
- ::Line(0, 0);
- ::RGBForeColor(&gAGARamp[r2]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.top + 1);
- ::Line(0, 0);
- }
-
- // Add arrow section shading.
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 2);
- ::LineTo(r.right - 3, r.bottom - 2);
- ::Line(0, -1);
- ::Line(1, 0);
- ::LineTo(r.right - 2, r.top + 3);
- ::Move(-1, -2);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Line(1, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(-1, 1);
- ::LineTo(r.right - 3, r.bottom - 4);
- ::Move(-1, 1);
- ::LineTo(r.right - kPopupArrowSectionWidth + 3, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[rW]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 4);
- ::LineTo(r.right - kPopupArrowSectionWidth + 2, r.top + 2);
- ::LineTo(r.right - 4, r.top + 2);
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRoundRect(&r, 7, 7);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRoundRect(&r, 7, 7);
- }
-
- // Add arrow.
- ::RGBForeColor(&gAGARamp[rB]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 6, r.top + 8);
- ::Line(8, 0);
- ::Move(-1, 1);
- ::Line(-6, 0);
- ::Move(1, 1);
- ::Line(4, 0);
- ::Move(-1, 1);
- ::Line(-2, 0);
- ::Line(1, 1);
-
- if (r.right - r.left > kPopupArrowSectionWidth)
- {
- // Draw the current item text.
- r.left += 7;
- r.right -= kPopupArrowSectionWidth;
- AGAStringOut(currentItemText, &r, truncEnd, teFlushDefault, kNormalOutput, deep, mTextStyle);
- }
-
- // If the popup has a title, draw it next to the button.
- if (mTitle[0] != 0)
- {
- this->GetTitleBounds(&r);
- AGAStringOut(mTitle, &r, truncEnd, mTitleJustification, kNormalOutput, deep, mTextStyle);
- }
-
- CleansePen();
- }
-
- void AGAPopupMenu::DrawButtonPressed(Boolean deep)
- {
- CleansePen();
-
- // Draw the popup button in enabled/pressed state.
-
- Rect r;
- Str255 currentItemText;
-
- this->GetCurrentItemText(currentItemText);
- this->GetButtonBounds(&r);
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r9]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(r.right - r.left - 6, 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, r.bottom - r.top - 6);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(- (r.right - r.left - 6), 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- ::Move(0, -1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::Line(0, -(r.bottom - r.top - 6));
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
-
- if (r.right - r.left > kPopupArrowSectionWidth)
- {
- // Add flat section inner pixels.
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 2);
- ::Line(1, 0);
- ::Line(0, -1);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.bottom - 2);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 2);
-
- // Add arrow section left corners
- ::RGBForeColor(&gAGARamp[r11]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.bottom - 2);
- ::Line(0, 0);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.top + 1);
- ::Line(0, 0);
- }
-
- // Add arrow section shading.
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 2);
- ::LineTo(r.right - 3, r.bottom - 2);
- ::Line(0, -1);
- ::Line(1, 0);
- ::LineTo(r.right - 2, r.top + 2);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::LineTo(r.right - 3, r.bottom - 4);
- ::Move(-1, 1);
- ::LineTo(r.right - kPopupArrowSectionWidth + 3, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 4);
- ::LineTo(r.right - kPopupArrowSectionWidth + 2, r.top + 2);
- ::LineTo(r.right - 4, r.top + 2);
- ::RGBForeColor(&gAGARamp[r11]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.bottom - 3);
- ::LineTo(r.right - kPopupArrowSectionWidth + 1, r.top + 2);
- ::Move(1, -1);
- ::LineTo(r.right - 3, r.top + 1);
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintRoundRect(&r, 7, 7);
- }
-
- // Add arrow.
-
- ::RGBForeColor(&gAGARamp[rW]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 6, r.top + 8);
- ::Line(8, 0);
- ::Move(-1, 1);
- ::Line(-6, 0);
- ::Move(1, 1);
- ::Line(4, 0);
- ::Move(-1, 1);
- ::Line(-2, 0);
- ::Line(1, 1);
-
- if (r.right - r.left > kPopupArrowSectionWidth)
- {
- // Draw the current item text.
- r.left += 7;
- r.right -= kPopupArrowSectionWidth;
- AGAStringOut(currentItemText, &r, truncEnd, teFlushDefault, kInverseOutput, deep, mTextStyle);
- }
-
- // (No need to draw the title, since it does not change
- // upon pressing the button.)
-
- CleansePen();
- }
-
- void AGAPopupMenu::DrawButtonDisabled(Boolean deep)
- {
- CleansePen();
-
- // Draw the popup button in disabled/unpressed state.
-
- Rect r;
- Str255 currentItemText;
-
- this->GetCurrentItemText(currentItemText);
- this->GetButtonBounds(&r);
-
- ::PenSize(1, 1);
-
- if (deep)
- {
- // Fill the interior.
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- // Draw the frame.
- ::MoveTo(r.left + 1, r.top + 1);
- ::RGBForeColor(&gAGARamp[r7]);
- ::Line(0, 0);
- ::Move(1, -1);
- ::Line(0, 0);
- ::Move(1, 0);
- ::Line(r.right - r.left - 6, 0);
- ::Line(0, 0);
- ::Move(1, 1);
- ::Line(0, 0);
- ::Move(1, 1);
- ::Line(0, 0);
- ::Move(0, 1);
- ::Line(0, r.bottom - r.top - 6);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::Line(0, 0);
- ::Move(-1, 1);
- ::Line(0, 0);
- ::Move(-1, 0);
- ::Line(- (r.right - r.left - 6), 0);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::Line(0, 0);
- ::Move(-1, -1);
- ::Line(0, 0);
- ::Move(0, -1);
- ::Line(0, -(r.bottom - r.top - 6));
- ::Line(0, 0);
-
- if (r.right - r.left > kPopupArrowSectionWidth)
- {
- // Add flat section inner pixels.
- ::RGBForeColor(&gAGARamp[r1]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 2);
- ::Line(1, 0);
- ::Line(0, -1);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.bottom - 2);
- ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 2);
- }
-
- // Add arrow section shading.
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 2);
- ::LineTo(r.right - 3, r.bottom - 2);
- ::Line(0, -1);
- ::Line(1, 0);
- ::LineTo(r.right - 2, r.top + 2);
- ::Move(-1, 1);
- ::RGBForeColor(&gAGARamp[r4]);
- ::LineTo(r.right - 3, r.bottom - 4);
- ::Move(-1, 1);
- ::LineTo(r.right - kPopupArrowSectionWidth + 3, r.bottom - 3);
- ::RGBForeColor(&gAGARamp[r1]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 4);
- ::LineTo(r.right - kPopupArrowSectionWidth + 2, r.top + 2);
- ::LineTo(r.right - 4, r.top + 2);
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRoundRect(&r, 7, 7);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRoundRect(&r, 7, 7);
- }
-
- // Add arrow.
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.right - kPopupArrowSectionWidth + 6, r.top + 8);
- ::Line(8, 0);
- ::Move(-1, 1);
- ::Line(-6, 0);
- ::Move(1, 1);
- ::Line(4, 0);
- ::Move(-1, 1);
- ::Line(-2, 0);
- ::Line(1, 1);
-
- if (r.right - r.left > kPopupArrowSectionWidth)
- {
- // Draw the current item text.
- r.left += 7;
- r.right -= kPopupArrowSectionWidth;
- AGAStringOut(currentItemText, &r, truncEnd, teFlushDefault, kDisabledOutput, deep, mTextStyle);
- }
-
- // If the popup has a title, draw it next to the button.
- if (mTitle[0] != 0)
- {
- this->GetTitleBounds(&r);
- AGAStringOut(mTitle, &r, truncEnd, mTitleJustification, kDisabledOutput, deep, mTextStyle);
- }
-
- if (! deep)
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenPat(&qd.gray);
- ::PenMode(patBic);
- ::PaintRect(&mBounds);
-
- ::PenNormal();
- }
-
- CleansePen();
- }
-
- void AGAPopupMenu::GetButtonBounds(Rect* buttonBounds)
- {
- // Return the bounds of the popup button. We may need
- // to check the actual menu's width, depending on the
- // width adjustment specifier.
-
- *buttonBounds = mBounds;
- buttonBounds->left += mTitleOffset;
-
- if ((mMenuRef != NULL) && (mWidthAdjust != kFixedWidth))
- {
- ::CalcMenuSize(mMenuRef);
- buttonBounds->right = MinSInt16(mBounds.right, buttonBounds->left + 3 + (**mMenuRef).menuWidth + mWidthAdjust);
- }
- }
-
- void AGAPopupMenu::GetTitleBounds(Rect* titleBounds)
- {
- // Return the bounds of the title area.
-
- *titleBounds = mBounds;
-
- titleBounds->right = titleBounds->left + mTitleOffset - 3;
- }
-
- //
- // AGALittleArrows ---------------------------------------------------------------
- //
- // This class implements a little arrows control.
- //
-
- AGALittleArrows::AGALittleArrows(Rect* bounds)
- : AGAObject(bounds)
- {
- mNotificationRoutine = NULL;
- mUserData = 0;
- }
-
- AGALittleArrows::~AGALittleArrows()
- {
- }
-
- void AGALittleArrows::InstallNotificationRoutine(AGALittleArrowsNotifyPtr notificationRoutine, void* userData)
- {
- // Install the supplied function pointer and user data to
- // be called during notification.
-
- mNotificationRoutine = notificationRoutine;
- mUserData = userData;
- }
-
- void AGALittleArrows::DrawObject()
- {
- // Draw the arrows in normal unpressed state.
-
- this->DrawButton(kNoArrowPressed);
- }
-
- Boolean AGALittleArrows::TrackMouse(Point mouseLocation)
- {
- // Track the mouse in the appropriate arrow. Little arrows
- // always return true because the tracking is always successful.
-
- return this->TrackPart(mouseLocation, this->TrackTestPart(mouseLocation));
- }
-
- void AGALittleArrows::DrawButton(SInt32 pressedPart)
- {
- CleansePen();
-
- // Draw the arrows in the specified press state. The
- // state may indicate that either or no arrow is pressed.
-
- enum { Frame, Fill, TL, BR, Arrow, kNumArrowColors };
-
- UInt8 colorIndexes[kNumArrowColors];
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- Rect r = mBounds;
-
- r.right = r.left + kLittleArrowWidth;
- r.bottom = r.top + kLittleArrowHeight;
-
- for (UInt32 i = 0; i < 2; i++)
- {
- if (deep)
- {
- if (mEnabled)
- {
- if (((pressedPart == kUpArrowPressed) && (i == 0)) ||
- ((pressedPart == kDownArrowPressed) && (i == 1)))
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = r8;
- colorIndexes[TL] = r10;
- colorIndexes[BR] = r6;
- colorIndexes[Arrow] = rW;
- }
- else if (((pressedPart != kUpArrowPressed) && (i == 0)) ||
- ((pressedPart != kDownArrowPressed) && (i == 1)))
- {
- colorIndexes[Frame] = rB;
- colorIndexes[Fill] = r2;
- colorIndexes[TL] = rW;
- colorIndexes[BR] = r5;
- colorIndexes[Arrow] = rB;
- }
- }
- else // disabled
- {
- colorIndexes[Frame] = r7;
- colorIndexes[Fill] = r2;
- colorIndexes[TL] = r1;
- colorIndexes[BR] = r5;
- colorIndexes[Arrow] = r7;
- }
-
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Frame]]);
- ::FrameRect(&r);
-
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
- ::PaintRect(&r);
- ::InsetRect(&r, -1, -1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 1);
- ::LineTo(r.right - 3, r.top + 1);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
- ::MoveTo(r.left + 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.right - 2, r.top + 2);
-
- ::RGBForeColor(&gAGARamp[colorIndexes[Arrow]]);
- }
- else // 1-bit
- {
- if (((pressedPart == kUpArrowPressed) && (i == 0)) ||
- ((pressedPart == kDownArrowPressed) && (i == 1)))
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintRect(&r);
- ::RGBForeColor(&gAGARamp[rW]);
- }
- else
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
- }
- }
-
- ::MoveTo(r.left + 3, r.top + 7 - (i*3));
- ::Line(6, 0);
- ::Move(-1, -1 + (2*i));
- ::Line(-4, 0);
- ::Move(1, -1 + (2*i));
- ::Line(2, 0);
- ::Move(-1, -1 + (2*i));
- ::Line(0, 0);
-
- ::OffsetRect(&r, 0, kLittleArrowHeight - 1);
- }
-
- if ((! mEnabled) && ! deep)
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenPat(&qd.gray);
- ::PenMode(patBic);
- ::PaintRect(&mBounds);
-
- ::PenNormal();
- }
- }
-
- CleansePen();
- }
-
- Boolean AGALittleArrows::TrackPart(Point mouseLocation, SInt32 partHit)
- {
- // Track the mouse in the specified arrow. Little arrows always
- // return true because the tracking is always successful.
-
- Boolean wasIn = FALSE;
- Boolean isIn = TRUE;
- Boolean isButtonDown = TRUE; // ensure at least one time through
- Point newMouseLocation;
- UInt32 accelerationDelay = 18; // will divide by 2 each time
-
- while (isButtonDown)
- {
- if (isIn)
- this->NotifyDelta(partHit);
-
- ::GetMouse(&newMouseLocation); // gives local coordinates
-
- isIn = (this->TrackTestPart(newMouseLocation) == partHit);
-
- if (isIn != wasIn)
- this->DrawButton(isIn ? partHit : kNoArrowPressed);
-
- wasIn = isIn;
-
- if (isButtonDown && (accelerationDelay != 0))
- {
- DelayFutureWhileStillDown(accelerationDelay);
- accelerationDelay = accelerationDelay >> 1; // divide by 2
- }
-
- isButtonDown = ::StillDown();
- }
-
- if (isIn) // if finished IN, restore normal appearance
- this->DrawButton(kNoArrowPressed);
-
- return TRUE;
- }
-
- SInt32 AGALittleArrows::TrackTestPart(Point mouseLocation)
- {
- // Return the part value where the mouse would hit.
-
- if ((mouseLocation.h >= mBounds.left + kLittleArrowWidth) ||
- (mouseLocation.h < mBounds.left) ||
- (mouseLocation.v >= mBounds.top + kLittleArrowTotalHeight) ||
- (mouseLocation.v < mBounds.top))
- return kNoArrowPressed;
- else if (mouseLocation.v < mBounds.top + kLittleArrowHeight)
- return kUpArrowPressed;
- else
- return kDownArrowPressed;
- }
-
- void AGALittleArrows::NotifyDelta(SInt32 partHit)
- {
- // Call the installed notification routine, if any, with
- // the installed user data and our part hit, which is the
- // value delta (-1 or 1).
-
- if (mNotificationRoutine != NULL)
- (*(mNotificationRoutine))(this, partHit, mUserData);
- }
-
- //
- // AGADisclosureTriangle ---------------------------------------------------------------
- //
- // This class implements a disclosure triangle.
- //
-
- AGADisclosureTriangle::AGADisclosureTriangle(Rect* bounds, Boolean automaticState)
- : AGAObject(bounds)
- {
- // Construct as specified.
-
- mAutomaticState = automaticState;
- mIsDisclosed = kClosedState;
- }
-
- AGADisclosureTriangle::~AGADisclosureTriangle()
- {
- }
-
- void AGADisclosureTriangle::DrawObject()
- {
- // Draw the triangle in the current state.
-
- this->DrawTriangle(mIsDisclosed ? kDTDisclosed : kDTClosed);
- }
-
- Boolean AGADisclosureTriangle::TrackMouse(Point mouseLocation)
- {
- // Let superclass handle tracking, and change our state
- // if we have automatic state change turned on.
-
- Boolean wasItHit = AGAObject::TrackMouse(mouseLocation);
-
- if (wasItHit && mAutomaticState)
- this->SetStateAnimate(! mIsDisclosed);
-
- return wasItHit;
- }
-
- Boolean AGADisclosureTriangle::GetState()
- {
- // Return the current state.
-
- return mIsDisclosed;
- }
-
- void AGADisclosureTriangle::SetState(Boolean isDisclosed, Boolean redraw)
- {
- // Set the state and optionally redraw.
-
- if (isDisclosed != mIsDisclosed)
- {
- mIsDisclosed = isDisclosed;
-
- if (redraw)
- {
- this->DrawTriangle(mIsDisclosed ? kDTDisclosed : kDTClosed);
- }
- }
- }
-
- void AGADisclosureTriangle::SetStateAnimate(Boolean isDisclosed)
- {
- // Set the state, but animate the triangle as it changes
- // to the new state.
-
- const SInt32 kAnimationDelay = 4;
-
- if (isDisclosed)
- {
- this->DrawTriangle(kDTPressedClosed);
- DelayFuture(kAnimationDelay);
-
- this->EraseBackground();
- this->DrawTriangle(kDTIntermediate);
- DelayFuture(kAnimationDelay);
-
- this->EraseBackground();
- this->DrawTriangle(kDTPressedDisclosed);
- DelayFuture(kAnimationDelay);
-
- this->EraseBackground();
- }
- else
- {
- this->DrawTriangle(kDTPressedDisclosed);
- DelayFuture(kAnimationDelay);
-
- this->EraseBackground();
- this->DrawTriangle(kDTIntermediate);
- DelayFuture(kAnimationDelay);
-
- this->EraseBackground();
- this->DrawTriangle(kDTPressedClosed);
- DelayFuture(kAnimationDelay);
-
- this->EraseBackground();
- }
-
- this->SetState(isDisclosed, kRedraw);
- }
-
- void AGADisclosureTriangle::SetTrackingState(Boolean isIn)
- {
- // Draw the triangle pressed or unpressed as specified.
-
- DTAnimationState state;
-
- if (isIn)
- state = mIsDisclosed ? kDTPressedDisclosed : kDTPressedClosed;
- else
- state = mIsDisclosed ? kDTDisclosed : kDTClosed;
-
- this->DrawTriangle(state);
- }
-
- void AGADisclosureTriangle::DrawTriangle(DTAnimationState state)
- {
- CleansePen();
-
- // Draw the triangle at the specified animation frame.
-
- Point fulcrum;
- Point corners[3];
-
- ::SetPt(&fulcrum, mBounds.left + 5, mBounds.top + 5);
-
- switch (state)
- {
- case kDTClosed:
- case kDTPressedClosed:
- ::SetPt(&corners[0], fulcrum.h - 2, fulcrum.v - 5);
- ::SetPt(&corners[1], fulcrum.h + 3, fulcrum.v);
- ::SetPt(&corners[2], fulcrum.h - 2, fulcrum.v + 5);
- break;
- case kDTIntermediate:
- ::SetPt(&corners[0], fulcrum.h + 3, fulcrum.v - 5);
- ::SetPt(&corners[1], fulcrum.h + 3, fulcrum.v + 3);
- ::SetPt(&corners[2], fulcrum.h - 5, fulcrum.v + 3);
- break;
- case kDTPressedDisclosed:
- case kDTDisclosed:
- ::SetPt(&corners[0], fulcrum.h + 5, fulcrum.v - 2);
- ::SetPt(&corners[1], fulcrum.h, fulcrum.v + 3);
- ::SetPt(&corners[2], fulcrum.h - 5, fulcrum.v - 2);
- break;
- }
-
- // Little trick: tweak state so that disabled state (gray
- // fill) is handled by pressed case code below. We already set
- // the color so they only set pressed fill color if enabled.
- DTAnimationState deepState = state;
-
- if (! mEnabled)
- {
- if (deepState == kDTClosed)
- deepState = kDTPressedClosed;
- else
- deepState = kDTPressedDisclosed;
- }
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[rB]);
- else
- ::RGBForeColor(&gAGARamp[r5]);
-
- ::MoveTo(corners[0].h, corners[0].v);
- ::LineTo(corners[1].h, corners[1].v);
- ::LineTo(corners[2].h, corners[2].v);
- ::LineTo(corners[0].h, corners[0].v);
-
- switch (deepState)
- {
- case kDTClosed:
- ::RGBForeColor(&gAGARamp[rA1]);
- ::MoveTo(corners[0].h + 1, corners[0].v + 2);
- ::Line(0, 6);
- ::RGBForeColor(&gAGARamp[rA2]);
- ::Line(1, -1);
- ::Line(0, -4);
- ::Line(1, 1);
- ::Line(0, 1);
- ::Move(1, 0);
- ::RGBForeColor(&gAGARamp[rA3]);
- ::Line(-2, 2);
-
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(corners[2].h + 1, corners[2].v);
- ::Line(4, -4);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Move(1, 0);
- ::Line(-5, 5);
- break;
- case kDTPressedClosed:
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[rA4]);
-
- ::MoveTo(corners[0].h + 1, corners[0].v + 2);
- ::Line(0, 6);
- ::Move(1, -1);
- ::Line(0, -4);
- ::Move(1, 1);
- ::Line(0, 2);
- ::Line(1, -1);
-
- ::RGBForeColor(&gAGARamp[r2]);
- ::MoveTo(corners[2].h + 1, corners[2].v);
- ::Line(4, -4);
- ::Move(1, 0);
- ::Line(-5, 5);
- break;
- case kDTIntermediate:
- ::RGBForeColor(&gAGARamp[rA4]);
- ::MoveTo(corners[0].h - 1, corners[0].v + 2);
- ::Line(-5, 5);
- ::Move(1, 0);
- ::Line(4, -4);
- ::Move(0, 1);
- ::Line(-3, 3);
- ::Move(1, 0);
- ::Line(2, -2);
- ::Move(0, 1);
- ::Line(-1, 1);
- ::Line(1, 0);
- break;
- case kDTPressedDisclosed:
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[rA4]);
-
- ::MoveTo(corners[2].h + 2, corners[2].v + 1);
- ::Line(6, 0);
- ::Move(-1, 1);
- ::Line(-4, 0);
- ::Move(1, 1);
- ::Line(2, 0);
- ::Line(-1, 1);
-
- ::RGBForeColor(&gAGARamp[r2]);
- ::MoveTo(corners[0].h, corners[0].v + 1);
- ::Line(-4, 4);
- ::Move(0, 1);
- ::Line(5, -5);
- break;
- case kDTDisclosed:
- ::RGBForeColor(&gAGARamp[rA1]);
- ::MoveTo(corners[2].h + 2, corners[2].v + 1);
- ::Line(6, 0);
- ::RGBForeColor(&gAGARamp[rA2]);
- ::Line(-1, 1);
- ::Line(-4, 0);
- ::Line(1, 1);
- ::Line(1, 0);
- ::Move(0, 1);
- ::RGBForeColor(&gAGARamp[rA3]);
- ::Line(2, -2);
-
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(corners[0].h, corners[0].v + 1);
- ::Line(-4, 4);
- ::RGBForeColor(&gAGARamp[r4]);
- ::Move(0, 1);
- ::Line(5, -5);
- break;
- }
- }
- else // 1-bit
- {
- PolyHandle theTriangle = ::OpenPoly();
-
- ::MoveTo(corners[0].h, corners[0].v);
- ::LineTo(corners[1].h, corners[1].v);
- ::LineTo(corners[2].h, corners[2].v);
- ::LineTo(corners[0].h, corners[0].v);
-
- ::ClosePoly();
-
- switch (state)
- {
- case kDTClosed:
- case kDTDisclosed:
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintPoly(theTriangle);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FramePoly(theTriangle);
-
- if (! mEnabled)
- {
- ::PenPat(&qd.gray);
- ::PenMode(patBic);
- ::PaintRect(&mBounds);
-
- ::PenNormal();
- }
- break;
- case kDTPressedClosed:
- case kDTIntermediate:
- case kDTPressedDisclosed:
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintPoly(theTriangle);
- break;
- }
-
- ::KillPoly(theTriangle);
- ::PenNormal();
- }
- }
-
- CleansePen();
- }
-
- void AGADisclosureTriangle::EraseBackground()
- {
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- ::RGBForeColor(&mBackgroundEraseColor);
- else
- ::RGBForeColor(&gAGARamp[rW]);
-
- ::PaintRect(&mBounds);
- }
- }
-
- //
- // AGAProgressIndicator ---------------------------------------------------------------
- //
- // This class implements a progress indicator that can be either
- // determinate or indeterminate, and also can have a moving start
- // value.
- //
-
- // We use an offscreen image for the indeterminate progress pattern.
- AGAOffscreenImage* AGAProgressIndicator::mgOffscreenIndeterminateProgressImage[kNumProgressPatterns];
-
- // These are the color ramp indexes that are used to build the offscreen image.
- SInt8 AGAProgressIndicator::kIndeterminateProgressImage[kNumProgressPatterns]
- [kProgressImageHeight]
- [kProgressImageWidth] =
- {
- { // k1BitPattern
- { rB, rB, rB, rB, rB, rB, rB, rB, rW, rW, rW, rW, rW, rW, rW, rW },
- { rW, rB, rB, rB, rB, rB, rB, rB, rB, rW, rW, rW, rW, rW, rW, rW },
- { rW, rW, rB, rB, rB, rB, rB, rB, rB, rB, rW, rW, rW, rW, rW, rW },
- { rW, rW, rW, rB, rB, rB, rB, rB, rB, rB, rB, rW, rW, rW, rW, rW },
- { rW, rW, rW, rW, rB, rB, rB, rB, rB, rB, rB, rB, rW, rW, rW, rW },
- { rW, rW, rW, rW, rW, rB, rB, rB, rB, rB, rB, rB, rB, rW, rW, rW },
- { rW, rW, rW, rW, rW, rW, rB, rB, rB, rB, rB, rB, rB, rB, rW, rW },
- { rW, rW, rW, rW, rW, rW, rW, rB, rB, rB, rB, rB, rB, rB, rB, rW },
- { rW, rW, rW, rW, rW, rW, rW, rW, rB, rB, rB, rB, rB, rB, rB, rB },
- { rB, rW, rW, rW, rW, rW, rW, rW, rW, rB, rB, rB, rB, rB, rB, rB },
- },
- { // kDeepPattern
- { rA, rA, rA, rA, rA, rA, rA, rA, r10, r10, r10, r10, r10, r10, r10, r10 },
- { r8, r10, r10, r10, r10, r10, r10, r10, r10, r8, r8, r8, r8, r8, r8, r8 },
- { r5, r5, r8, r8, r8, r8, r8, r8, r8, r8, r5, r5, r5, r5, r5, r5 },
- { r2, r2, r2, r5, r5, r5, r5, r5, r5, r5, r5, r2, r2, r2, r2, r2 },
- { rW, rW, rW, rW, r3, r3, r3, r3, r3, r3, r3, r3, rW, rW, rW, rW },
- { r2, r2, r2, r2, r2, r5, r5, r5, r5, r5, r5, r5, r5, r2, r2, r2 },
- { r4, r4, r4, r4, r4, r4, r8, r8, r8, r8, r8, r8, r8, r8, r4, r4 },
- { r6, r6, r6, r6, r6, r6, r6, r10, r10, r10, r10, r10, r10, r10, r10, r6 },
- { r8, r8, r8, r8, r8, r8, r8, r8, rA, rA, rA, rA, rA, rA, rA, rA },
- { r12, r10, r10, r10, r10, r10, r10, r10, r10, r12, r12, r12, r12, r12, r12, r12 },
- },
- };
-
- OSErr AGAProgressIndicator::AllocateProgressImages()
- {
- // Allocate the offscreen image for each radio button state.
-
- OSErr result = noErr;
- Point imageSize;
-
- imageSize.h = kProgressImageWidth;
- imageSize.v = kProgressImageHeight;
-
- for (UInt32 imageIndex = 0; imageIndex < kNumProgressPatterns; imageIndex++)
- {
- if (result == noErr)
- {
- mgOffscreenIndeterminateProgressImage[imageIndex] = new AGAOffscreenImage;
-
- result = mgOffscreenIndeterminateProgressImage[imageIndex]->CreateImageData(
- imageSize,
- &kIndeterminateProgressImage[imageIndex][0][0],
- NULL);
- }
- }
-
- return result;
- }
-
- void AGAProgressIndicator::DisposeProgressImages()
- {
- for (UInt32 imageIndex = 0; imageIndex < kNumProgressPatterns; imageIndex++)
- if (mgOffscreenIndeterminateProgressImage[imageIndex] != NULL)
- delete mgOffscreenIndeterminateProgressImage[imageIndex];
- }
-
- AGAProgressIndicator::AGAProgressIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum)
- : AGAObject(bounds)
- {
- // Construct with default options.
- // (minimum == maximum) means indeterminate indicator.
-
- mMinimum = minimum;
- mMaximum = maximum;
- mValue = minimum;
- mOriginValue = minimum;
- mAnimationIndex = 0;
- }
-
- AGAProgressIndicator::~AGAProgressIndicator()
- {
- }
-
- void AGAProgressIndicator::DrawObject()
- {
- // Draw at current gauge value or next animation step.
-
- this->DrawFrame();
-
- if (mMinimum == mMaximum)
- this->DrawAnimationStep();
- else
- this->DrawGauge();
- }
-
- SInt32 AGAProgressIndicator::GetValue()
- {
- // Return current value.
-
- return mValue;
- }
-
- void AGAProgressIndicator::SetValue(SInt32 newValue, Boolean redraw)
- {
- // Set gauge value, optionally redraw.
-
- // Constrain: mMinimum <= mValue <= mMaximum
- newValue = MaxSInt32(mMinimum, MinSInt32(newValue, mMaximum));
-
- if (newValue != mValue)
- {
- mValue = newValue;
-
- if (redraw)
- this->DrawGauge();
- }
- }
-
- void AGAProgressIndicator::Increment(SInt32 delta, Boolean redraw)
- {
- // Increment gauge value, optionally redraw.
-
- this->SetValue(delta + this->GetValue(), redraw);
- }
-
- void AGAProgressIndicator::Animate()
- {
- // Draw the next animation step.
-
- mAnimationIndex = (mAnimationIndex + 1) % kNumProgressAnimationSteps;
-
- this->DrawAnimationStep();
- }
-
- void AGAProgressIndicator::GetRange(SInt32* minimum, SInt32* maximum)
- {
- // Return the gauge value range.
-
- *minimum = mMinimum;
- *maximum = mMaximum;
- }
-
- void AGAProgressIndicator::SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw)
- {
- // Set the gauge value range, optionally redraw.
- // (minimum == maximum) means indeterminate indicator.
-
- if (mOriginValue == mMinimum)
- mOriginValue = newMinimum;
-
- mMinimum = newMinimum;
- mMaximum = MaxSInt32(newMinimum, newMaximum);
-
- if (redraw)
- this->DrawObject();
- }
-
- SInt32 AGAProgressIndicator::GetOriginValue()
- {
- // Return the optional gauge origin value.
-
- return mOriginValue;
- }
-
- void AGAProgressIndicator::SetOriginValue(SInt32 newValue, Boolean redraw)
- {
- // Set the optional gauge origin value.
-
- // Constrain: mMinimum <= mOriginValue <= mValue
- newValue = MaxSInt32(mMinimum, MinSInt32(newValue, mValue));
-
- if (newValue != mOriginValue)
- {
- mOriginValue = newValue;
-
- if (redraw)
- this->DrawObject();
- }
- }
-
- void AGAProgressIndicator::DrawFrame()
- {
- CleansePen();
-
- // Draw the constant frame around the indicator.
- Rect r = mBounds;
-
- r.bottom = r.top + kProgressHeight;
-
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.left, r.bottom - 2);
- ::LineTo(r.left, r.top);
- ::LineTo(r.right - 2, r.top);
-
- ::RGBForeColor(&gAGARamp[rW]);
- ::MoveTo(r.left + 1, r.bottom - 1);
- ::LineTo(r.right - 1, r.bottom - 1);
- ::LineTo(r.right - 1, r.top + 1);
- }
-
- ::InsetRect(&r, 1, 1);
- ::RGBForeColor(&gAGARamp[rB]);
- ::FrameRect(&r);
- ::InsetRect(&r, -1, -1);
- }
-
- CleansePen();
- }
-
- void AGAProgressIndicator::DrawAnimationStep()
- {
- CleansePen();
-
- // Draw the indeterminate progress indicator at the
- // current animation step.
-
- const UInt32 kNumRows = 10;
-
- Rect r = mBounds;
- SInt16 patternHOrigin;
-
- r.bottom = r.top + kProgressHeight;
- ::InsetRect(&r, 2, 2);
-
- //
- // Move the pen leftward so the pattern is offset for
- // the current animation step. This will mean we need
- // to explicitly clip to our gauge area, since our pattern
- // origin is outside it.
- //
-
- patternHOrigin = r.left - 32 + ((16 / kNumProgressAnimationSteps) * mAnimationIndex);
-
- RgnHandle savedClip = ::NewRgn();
- ::GetClip(savedClip);
-
- AGAClipFurther(&r);
-
- r.left = patternHOrigin;
-
- {
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- mgOffscreenIndeterminateProgressImage[kDeepPattern]->DrawPattern(&r);
- else
- mgOffscreenIndeterminateProgressImage[k1BitPattern]->DrawPattern(&r);
- }
- } // force GDIterator clip to clean up now, not after we set savedClip!
-
- ::SetClip(savedClip);
- ::DisposeRgn(savedClip);
-
- CleansePen();
- }
-
- void AGAProgressIndicator::DrawGauge()
- {
- // Draw the determinate progress indicator.
-
- if (mOriginValue != mMinimum)
- this->DrawOriginArea();
-
- this->DrawProgressArea();
- this->DrawRemainderArea();
- }
-
- void AGAProgressIndicator::DrawOriginArea()
- {
- // Draw the empty track between the minimum value
- // and the origin value.
-
- Rect frame;
-
- if (this->GetOriginFrame(&frame))
- {
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- Rect r = frame;
-
- if (deep)
- {
- SInt16 width = r.right - r.left;
-
- if (width >= 0)
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::MoveTo(r.right, r.top);
- ::LineTo(r.right, r.bottom - 1);
- }
-
- if (width > 0)
- {
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.left, r.top);
- ::LineTo(r.left, r.bottom - 1);
- }
-
- if (width > 1)
- {
- ::RGBForeColor(&gAGARamp[r4]);
- ::MoveTo(r.right - 1, r.top);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::LineTo(r.right - 1, r.bottom - 1);
- }
-
- if (width > 2)
- {
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.left + 1, r.top);
- ::LineTo(r.left + 1, r.bottom - 1);
- }
-
- if (width > 3)
- {
- ::RGBForeColor(&gAGARamp[r2]);
- ::MoveTo(r.left + 2, r.bottom - 1);
- ::LineTo(r.right - 1, r.bottom - 1);
-
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.left + 2, r.top);
- ::LineTo(r.right - 2, r.top);
-
- ::RGBForeColor(&gAGARamp[r4]);
- r.left += 2;
- r.top++;
- r.bottom--;
- r.right--;
- ::PaintRect(&r);
- }
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- }
- }
- }
-
- CleansePen();
- }
-
- void AGAProgressIndicator::DrawProgressArea()
- {
- CleansePen();
-
- // Draw the filled progress gauge area between
- // the origin and the current value.
-
- Rect frame;
-
- if (this->GetProgressFrame(&frame))
- {
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- Rect r = frame;
-
- if (deep)
- {
- SInt16 width = r.right - r.left;
-
- //
- // Because the endcaps of the gauge are shaded,
- // we need to carefully draw the ends horizontal
- // pixel by pixel, bailing out if there is not
- // enough width to accomodate the endcaps and the
- // midsection.
- //
-
- if (width > 0)
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::MoveTo(r.right - 1, r.top);
- ::LineTo(r.right - 1, r.bottom - 1);
- }
-
- if (width > 1)
- {
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left, r.top);
- ::LineTo(r.left, r.bottom - 1);
- }
-
- if (width > 2)
- {
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.right - 2, r.top);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::LineTo(r.right - 2, r.bottom - 1);
- }
-
- if (width > 3)
- {
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left + 1, r.top);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r3]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r1]);
- ::Line(0, 3);
- ::RGBForeColor(&gAGARamp[r3]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r10]);
- ::Line(0, 0);
- }
-
- if (width > 4)
- {
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.right - 3, r.top);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r10]);
- ::LineTo(r.right - 3, r.bottom - 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- }
-
- if (width > 5)
- {
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.right - 4, r.top);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r3]);
- ::Line(0, 3);
- ::RGBForeColor(&gAGARamp[r5]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r8]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r10]);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r12]);
- ::Line(0, 0);
- }
-
- if (width > 6)
- {
- SInt16 distance = width - 7;
-
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.left + 2, r.top);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left + 2, r.top + 1);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.left + 2, r.top + 2);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r3]);
- ::MoveTo(r.left + 2, r.top + 3);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r1]);
- ::MoveTo(r.left + 2, r.top + 4);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r3]);
- ::MoveTo(r.left + 2, r.top + 5);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r5]);
- ::MoveTo(r.left + 2, r.top + 6);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r8]);
- ::MoveTo(r.left + 2, r.top + 7);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.left + 2, r.top + 8);
- ::Line(distance, 0);
- ::RGBForeColor(&gAGARamp[r12]);
- ::MoveTo(r.left + 2, r.top + 9);
- ::Line(distance, 0);
- }
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PaintRect(&r);
- }
- }
- }
-
- CleansePen();
- }
-
- void AGAProgressIndicator::DrawRemainderArea()
- {
- CleansePen();
-
- // Draw the empty track area between the current
- // gauge value and the maximum.
-
- Rect frame;
-
- if (this->GetRemainderFrame(&frame))
- {
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- Rect r = frame;
-
- if (deep)
- {
- SInt16 width = r.right - r.left;
-
- if (width > 0)
- {
- ::RGBForeColor(&gAGARamp[r10]);
- ::MoveTo(r.left, r.top);
- ::LineTo(r.left, r.bottom - 1);
- }
-
- if (width > 1)
- {
- ::RGBForeColor(&gAGARamp[r4]);
- ::MoveTo(r.right - 1, r.top);
- ::Line(0, 1);
- ::RGBForeColor(&gAGARamp[r2]);
- ::LineTo(r.right - 1, r.bottom - 1);
- }
-
- if (width > 2)
- {
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.left + 1, r.top);
- ::LineTo(r.left + 1, r.bottom - 1);
- }
-
- if (width > 3)
- {
- ::RGBForeColor(&gAGARamp[r2]);
- ::MoveTo(r.left + 2, r.bottom - 1);
- ::LineTo(r.right - 1, r.bottom - 1);
-
- ::RGBForeColor(&gAGARamp[r7]);
- ::MoveTo(r.left + 2, r.top);
- ::LineTo(r.right - 2, r.top);
-
- ::RGBForeColor(&gAGARamp[r4]);
- r.left += 2;
- r.top++;
- r.bottom--;
- r.right--;
- ::PaintRect(&r);
- }
- }
- else // 1-bit
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::PaintRect(&r);
- }
- }
- }
-
- CleansePen();
- }
-
- Boolean AGAProgressIndicator::GetOriginFrame(Rect* originFrame)
- {
- // Return true (and the area) if there is an area
- // to be drawn for the empty origin part of the track.
-
- Boolean isNeeded = FALSE;
-
- if (mOriginValue != mMinimum)
- {
- isNeeded = TRUE;
-
- this->GetRangeFrame(mMinimum, mOriginValue, originFrame);
-
- if (mOriginValue != mMaximum)
- originFrame->right--;
- }
-
- return isNeeded;
- }
-
- Boolean AGAProgressIndicator::GetProgressFrame(Rect* progressFrame)
- {
- // Return true (and the area) if there is an area
- // to be drawn for the progress section of the gauge.
-
- Boolean isNeeded = FALSE;
-
- if (mValue != mOriginValue)
- {
- isNeeded = TRUE;
-
- this->GetRangeFrame(mOriginValue, mValue, progressFrame);
-
- if (mValue == mMaximum)
- progressFrame->right++;
- }
-
- return isNeeded;
- }
-
- Boolean AGAProgressIndicator::GetRemainderFrame(Rect* remainderFrame)
- {
- // Return true (and the area) if there is an area
- // to be drawn for the uncompleted gauge remainder area.
-
- Boolean isNeeded = FALSE;
-
- if (mMaximum != mValue)
- {
- isNeeded = TRUE;
-
- this->GetRangeFrame(mValue, mMaximum, remainderFrame);
- }
-
- return isNeeded;
- }
-
- void AGAProgressIndicator::GetRangeFrame(SInt32 startValue, SInt32 endValue, Rect* rangeFrame)
- {
- // Return the rectangle that the indicator draws in,
- // which does not include the constant border frame area.
-
- *rangeFrame = mBounds;
- rangeFrame->bottom = rangeFrame->top + kProgressHeight;
-
- ::InsetRect(rangeFrame, 2, 2);
-
- SInt32 divisor = mMaximum - mMinimum;
-
- if (divisor != 0) // avoid divide by zero
- {
- SInt32 totalWidth = rangeFrame->right - rangeFrame->left;
- float startFraction = ((float) (startValue - mMinimum)) / divisor;
- float endFraction = ((float) (endValue - mMinimum)) / divisor;
-
- rangeFrame->right = rangeFrame->left + (endFraction * totalWidth);
- rangeFrame->left = rangeFrame->left + (startFraction * totalWidth);
- }
- }
-
- //
- // AGASeparator ---------------------------------------------------------------
- //
- // This class draws a separator line. It knowns whether it's horizontal or
- // vertical based on the larger dimension.
- //
-
- AGASeparator::AGASeparator(Rect* bounds)
- : AGAObject(bounds)
- {
- // Call superclass constructor.
- }
-
- AGASeparator::~AGASeparator()
- {
- }
-
- void AGASeparator::DrawObject()
- {
- CleansePen();
-
- // Draw the separator along the leading edge in
- // its longest dimension.
-
- Boolean isHorizontal = ((mBounds.right - mBounds.left) > (mBounds.bottom - mBounds.top));
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- ::RGBForeColor(&gAGARamp[r7]);
- else
- {
- ::RGBForeColor(&gAGARamp[rB]);
- ::PenPat(&qd.gray);
- }
-
- ::MoveTo(mBounds.left, mBounds.top);
-
- if (isHorizontal)
- ::LineTo(mBounds.right - 2, mBounds.top);
- else
- ::LineTo(mBounds.left, mBounds.bottom - 2);
-
- if (deep)
- {
- ::RGBForeColor(&gAGARamp[rW]);
- ::MoveTo(mBounds.left + 1, mBounds.top + 1);
-
- if (isHorizontal)
- ::LineTo(mBounds.right - 1, mBounds.top + 1);
- else
- ::LineTo(mBounds.left + 1, mBounds.bottom - 1);
- }
- else
- ::PenPat(&qd.black);
- }
-
- CleansePen();
- }
-
- //
- // AGAGroupBox ---------------------------------------------------------------
- //
- // This class draws primary and secondary group boxes, with optional
- // title label or title gap for a separate control.
- //
-
- AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType)
- : AGAObject(bounds)
- {
- // Construct without a title or gap.
-
- mIsPrimaryBox = groupBoxType;
- mTitleGap = 0;
- mTitle[0] = 0;
- mTextStyle = textStyle;
- }
-
- AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, SInt16 titleGap)
- : AGAObject(bounds)
- {
- // Construct with specified gap.
-
- mIsPrimaryBox = groupBoxType;
- mTitleGap = titleGap;
- mTitle[0] = 0;
- mTextStyle = textStyle;
- }
-
- AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, StringPtr titleString)
- : AGAObject(bounds)
- {
- // Construct with specified title.
-
- mIsPrimaryBox = groupBoxType;
- mTitleGap = 0;
- PLstrcpy(mTitle, titleString);
- mTextStyle = textStyle;
- }
-
- AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, SInt16 titleStringListResourceID, SInt16 titleStringIndex)
- : AGAObject(bounds)
- {
- // Construct by getting title from specified resource.
-
- mIsPrimaryBox = groupBoxType;
- mTitleGap = 0;
- ::GetIndString(mTitle, titleStringListResourceID, titleStringIndex);
- mTextStyle = textStyle;
- }
-
- AGAGroupBox::~AGAGroupBox()
- {
- }
-
- void AGAGroupBox::SetTitleGap(SInt16 titleGap)
- {
- // Set the width of the title gap that will be left blank.
-
- mTitleGap = titleGap;
- }
-
- void AGAGroupBox::SetTitle(StringPtr newTitle, Boolean redraw)
- {
- // Set the title, optionally redraw.
-
- PLstrcpy(mTitle, newTitle);
-
- if (redraw)
- this->DrawObject();
- }
-
- void AGAGroupBox::DrawObject()
- {
- CleansePen();
-
- // Draw the group box.
-
- Rect r = mBounds;
- SInt16 titleGap = 0;
- SInt16 topIndent = 0;
- FontInfo fontInfo;
-
- if (mTitle[0] != 0)
- {
- ::TextFont(0);
- ::TextSize(0);
- ::TextFace(0);
- ::GetFontInfo(&fontInfo);
-
- topIndent = fontInfo.ascent; // text baseline should be at frame top
-
- titleGap = 5 + ::StringWidth(mTitle);
- }
- else
- titleGap = mTitleGap;
-
- if (mIsPrimaryBox)
- this->DrawPrimaryFrame(topIndent, titleGap);
- else
- this->DrawSecondaryFrame(topIndent, titleGap);
-
- if (mTitle[0] != 0)
- {
- Rect titleRect;
-
- titleRect.left = r.left + 14;
- titleRect.top = r.top + 2;
- titleRect.right = titleRect.left + titleGap;
- titleRect.bottom = titleRect.top + fontInfo.ascent + fontInfo.descent;
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- AGAStringOut(mTitle, &titleRect, kNoTruncation, teFlushDefault, mEnabled ? kNormalOutput : kDisabledOutput, deep, mTextStyle);
- }
-
- CleansePen();
- }
-
- void AGAGroupBox::DrawPrimaryFrame(SInt16 topIndent, SInt16 gapSize)
- {
- // Draw the group box as a primary group.
-
- Rect r = mBounds;
-
- r.top += topIndent;
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[r7]);
- else
- ::RGBForeColor(&gAGARamp[r4]);
- }
- else
- {
- ::RGBForeColor(&gAGARamp[rB]);
-
- if (! mEnabled)
- ::PenPat(&qd.gray);
- }
-
- ::MoveTo(r.right - 2, r.top);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.left, r.bottom - 2);
- ::LineTo(r.left, r.top);
- ::Line(10, 0);
- ::Move(gapSize, 0);
- ::LineTo(r.right - 2, r.top);
-
- if (deep)
- {
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[rW]);
- else
- ::RGBForeColor(&gAGARamp[r1]);
-
- ::MoveTo(r.right - 1, r.top);
- ::LineTo(r.right - 1, r.bottom - 1);
- ::LineTo(r.left, r.bottom - 1);
- ::MoveTo(r.left + 1, r.bottom - 3);
- ::LineTo(r.left + 1, r.top + 1);
- ::Line(9, 0);
- ::Move(gapSize, 0);
- ::LineTo(r.right - 3, r.top + 1);
- }
- else
- ::PenPat(&qd.black);
- }
- }
-
- void AGAGroupBox::DrawSecondaryFrame(SInt16 topIndent, SInt16 gapSize)
- {
- // Draw the group box as a secondary group.
-
- Rect r = mBounds;
-
- r.top += topIndent;
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- if (deep)
- {
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[rW]);
- else
- ::RGBForeColor(&gAGARamp[r1]);
-
- ::MoveTo(r.right - 1, r.top + 1);
- ::LineTo(r.right - 1, r.bottom - 1);
- ::LineTo(r.left + 1, r.bottom - 1);
-
- if (mEnabled)
- ::RGBForeColor(&gAGARamp[r7]);
- else
- ::RGBForeColor(&gAGARamp[r4]);
-
- ::MoveTo(r.left, r.bottom - 2);
- ::LineTo(r.left, r.top);
- ::Line(10, 0);
- ::Move(gapSize, 0);
- ::LineTo(r.right - 2, r.top);
- }
- else
- {
- ::RGBForeColor(&gAGARamp[rB]);
-
- if (! mEnabled)
- ::PenPat(&qd.gray);
-
- ::MoveTo(r.right - 2, r.top);
- ::LineTo(r.right - 2, r.bottom - 2);
- ::LineTo(r.left, r.bottom - 2);
- ::LineTo(r.left, r.top);
- ::Line(10, 0);
- ::Move(gapSize, 0);
- ::LineTo(r.right - 2, r.top);
-
- if (! mEnabled)
- ::PenPat(&qd.black);
- }
- }
- }
-
- //
- // AGAStringOut --------------------------------------------------------
- //
- // This is the routine we use for all of our text output.
- //
-
- void AGAStringOut(StringPtr aString,
- Rect* centeringFrame,
- SInt32 truncation,
- SInt32 justification,
- AGAStringOutColor outColor,
- Boolean deep,
- const AGATextStyle& textStyle)
- {
- Str255 outputString;
- FontInfo fontInfo;
- SInt16 frameWidth = centeringFrame->right - centeringFrame->left;
- SInt16 frameHeight = centeringFrame->bottom - centeringFrame->top;
- Point penOrigin;
- Boolean setColor = TRUE;
- UInt8 colorIndex;
-
- textStyle.PrepareForDrawing();
- ::GetFontInfo(&fontInfo);
-
- switch (outColor)
- {
- case kNormalOutput:
- colorIndex = rB;
- break;
- case kDisabledOutput:
- if (deep)
- colorIndex = r7;
- else
- colorIndex = rB;
- break;
- case kInverseOutput:
- colorIndex = rW;
- break;
- case kUseCurrentColor:
- setColor = FALSE;
- break;
- }
-
- if (setColor)
- ::RGBForeColor(&gAGARamp[colorIndex]);
-
- PLstrcpy(outputString, aString);
-
- // Truncate the string if it does not fit the width of the frame.
- if (truncation != kNoTruncation)
- {
- // If the string would be truncated at the current
- // font settings, try again with condensed text.
- if (::TruncString(frameWidth, outputString, truncation) == truncated)
- {
- PLstrcpy(outputString, aString);
- ::TextFace(condense);
- (void) ::TruncString(frameWidth, outputString, truncation);
- }
- }
-
- // Center the text vertically. Pen goes at baseline of
- // text, i.e. between the ascent and descent.
- penOrigin.v = centeringFrame->top + (frameHeight / 2) + ((fontInfo.ascent + fontInfo.descent) / 2) - fontInfo.descent;
-
- // Position the text horizontally left, centered, or right, based
- // on the specified justification and the system script direction.
- switch (RuntimeJustify(justification))
- {
- case teCenter:
- penOrigin.h = centeringFrame->left + (frameWidth / 2) - (::StringWidth(outputString) / 2);
- break;
- case teFlushRight:
- penOrigin.h = centeringFrame->right - ::StringWidth(outputString);
- break;
- default: //case teFlushLeft:
- penOrigin.h = centeringFrame->left;
- break;
- }
-
- ::MoveTo(penOrigin.h, penOrigin.v);
-
- GrafPtr currentPort;
- ::GetPort(¤tPort);
- SInt16 savedTxMode = currentPort->txMode;
- ::TextMode(srcOr);
- ::DrawString(outputString);
- ::TextMode(savedTxMode);
-
- if ((outColor == kDisabledOutput) && ! deep)
- {
- ::PenPat(&qd.gray);
- ::PenMode(patBic);
- ::PaintRect(centeringFrame);
-
- ::PenNormal();
- }
- }
-
- //
- // GDIterator -----------------------------------------------------
- //
-
- RgnHandle GDIterator::mSavedClipping = ::NewRgn();
-
- GDIterator::GDIterator()
- {
- this->Setup();
- }
-
- GDIterator::~GDIterator()
- {
- this->Cleanup();
- }
-
- void GDIterator::Setup()
- {
- ::GetClip(mSavedClipping);
-
- mIteratedYet = FALSE;
- mCurrentGDHandle = NULL;
- }
-
- Boolean GDIterator::More(Boolean& deep)
- {
- if (gAGAHasColorQD)
- {
- mCurrentGDHandle = this->FindNextValidDevice(mCurrentGDHandle, deep);
- return (mCurrentGDHandle != NULL);
- }
- else
- {
- deep = FALSE;
- return ! mIteratedYet;
- }
- }
-
- void GDIterator::Cleanup()
- {
- ::SetClip(mSavedClipping);
- }
-
- void GDIterator::ClipFurtherToCurrentDevice()
- {
- this->ClipFurtherToDevice(mCurrentGDHandle);
- }
-
- GDHandle GDIterator::FindNextValidDevice(GDHandle currentDevice, Boolean& deep)
- {
- GDHandle deviceToTest;
- GDHandle deviceFound = NULL;
-
- deep = FALSE;
-
- if (currentDevice == NULL)
- deviceToTest = ::GetMainDevice();
- else
- deviceToTest = ::GetNextDevice(currentDevice);
-
- while ((deviceToTest != NULL) && (deviceFound == NULL))
- {
- Boolean isValidDevice = FALSE;
-
- if (::TestDeviceAttribute(deviceToTest, screenDevice))
- if (::TestDeviceAttribute(deviceToTest, screenActive))
- {
- isValidDevice = TRUE;
-
- SInt16 pixelDepth = (**((**deviceToTest).gdPMap)).pixelSize;
- Boolean isColor = ::TestDeviceAttribute(deviceToTest, gdDevType);
-
- deep = (pixelDepth >= 8) || ((pixelDepth >= 4) && ! isColor);
-
- deviceFound = deviceToTest;
- }
-
- if (! isValidDevice)
- deviceToTest = ::GetNextDevice(deviceToTest);
- }
-
- if (deviceFound != NULL)
- {
- ::SetClip(mSavedClipping);
- this->ClipFurtherToDevice(deviceFound);
- }
-
- return deviceFound;
- }
-
- void GDIterator::ClipFurtherToDevice(GDHandle aDevice)
- {
- if (aDevice != NULL)
- {
- Rect deviceRect = (**aDevice).gdRect;
- Point drTopLeft;
- Point drBotRight;
-
- ::SetPt(&drTopLeft, deviceRect.left, deviceRect.top);
- ::SetPt(&drBotRight, deviceRect.right, deviceRect.bottom);
-
- ::GlobalToLocal(&drTopLeft);
- ::GlobalToLocal(&drBotRight);
-
- ::SetRect(&deviceRect, drTopLeft.h, drTopLeft.v, drBotRight.h, drBotRight.v);
-
- AGAClipFurther(&deviceRect);
- }
- }
-
- //
- // AGABackgroundPaint ------------------------------------------------
- //
-
- void AGABackgroundPaint(const Rect* backgroundBounds,
- Boolean drawFill,
- Boolean isModal,
- Boolean isActive,
- Boolean hasGrowBox)
- {
- CleansePen();
-
- // Draw in the specified active/inactive state.
-
- enum { kBGFill, kBGActiveLight, kBGActiveShadow, kBGInactiveLight, kBGInactiveShadow, kBGNumIndexes };
-
- UInt8 colorIndexes[kBGNumIndexes];
-
- if (isModal)
- {
- colorIndexes[kBGFill] = r2;
- colorIndexes[kBGActiveLight] = rW;
- colorIndexes[kBGActiveShadow] = r5;
- colorIndexes[kBGInactiveLight] = r1;
- colorIndexes[kBGInactiveShadow] = r4;
- }
- else
- {
- colorIndexes[kBGFill] = r2;
- colorIndexes[kBGActiveLight] = rW;
- colorIndexes[kBGActiveShadow] = r6;
- colorIndexes[kBGInactiveLight] = r1;
- colorIndexes[kBGInactiveShadow] = r4;
- }
-
- GDIterator iter;
- Boolean deep;
-
- while (iter.More(deep))
- {
- Rect r = *backgroundBounds;
-
- if (deep)
- {
- ::InsetRect(&r, 1, 1);
-
- if (drawFill)
- {
- ::RGBForeColor(&gAGARamp[colorIndexes[kBGFill]]);
-
- ::PaintRect(&r);
- ::MoveTo(r.left - 1, r.bottom);
- ::Line(0, 0);
- ::MoveTo(r.right, r.top - 1);
- ::Line(0, 0);
- }
-
- if (isActive)
- ::RGBForeColor(&gAGARamp[colorIndexes[kBGActiveLight]]);
- else
- ::RGBForeColor(&gAGARamp[colorIndexes[kBGInactiveLight]]);
-
- ::MoveTo(r.left - 1, r.bottom - 1);
- ::LineTo(r.left - 1, r.top - 1);
- ::LineTo(r.right - 1, r.top - 1);
-
- if (isActive)
- ::RGBForeColor(&gAGARamp[colorIndexes[kBGActiveShadow]]);
- else
- ::RGBForeColor(&gAGARamp[colorIndexes[kBGInactiveShadow]]);
-
- ::MoveTo(r.left, r.bottom);
-
- if (hasGrowBox)
- {
- ::LineTo(r.right - 15, r.bottom);
- ::Line(0, -15);
- ::Line(15, 0);
- }
- else
- ::LineTo(r.right, r.bottom);
-
- ::LineTo(r.right, r.top);
- }
- else // 1-bit
- {
- if (drawFill)
- {
- ::RGBBackColor(&gAGARamp[rW]);
- ::EraseRect(&r);
- }
- }
- }
-
- CleansePen();
- }
-
- //
- // AGAClipFurther ------------------------------------------------
- //
-
- void AGAClipFurther(Rect* clippingRect)
- {
- RgnHandle oldClip = ::NewRgn();
- RgnHandle newClip = ::NewRgn();
-
- if ((oldClip != NULL) && (newClip != NULL))
- {
- ::GetClip(oldClip);
- ::RectRgn(newClip, clippingRect);
-
- ::SectRgn(oldClip, newClip, newClip);
- ::SetClip(newClip);
-
- ::DisposeRgn(oldClip);
- ::DisposeRgn(newClip);
- }
- }
-
- //
- // CleansePen ------------------------------------------------
- //
-
- void CleansePen()
- {
- // We use this at the beginning and ending of all drawing methods.
- // It sets up the pen for our drawing, and it cleans up after us.
- //
- // We could require the caller (the MA or PP adapter classes) to
- // always clean things up only and exactly when their own
- // particular drawing environment requires, but it's simpler if
- // we just do it ourself to ensure that our environment is OK for
- // our needs, and that we leave it in a standard state when done.
-
- ::PenNormal(); // pen size 1,1, solid black pattern, srcOr
- ::RGBForeColor(&gAGARamp[rB]); // black fore color
- ::RGBBackColor(&gAGARamp[rW]); // white back color
- gAGAStdSystemStyle.PrepareForDrawing(); // system font 12 point
- }
-
-
- //
- // AGA Defaults ------------------------------------------------
- //
-
- void SetGrayCouncilDefault(UInt32 itemMask, Boolean turnOn)
- {
- if (turnOn)
- gAGADefaults |= itemMask;
- else
- gAGADefaults &= ~itemMask;
- }
-
- Boolean TestGrayCouncilDefault(UInt32 itemMask)
- {
- return ((gAGADefaults & itemMask) != 0);
- }
-
-